Skip to content

Change return-type-notation to use (..) #127092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -176,6 +176,8 @@ pub enum GenericArgs {
AngleBracketed(AngleBracketedArgs),
/// The `(A, B)` and `C` in `Foo(A, B) -> C`.
Parenthesized(ParenthesizedArgs),
/// `(..)` in return type notation
ParenthesizedElided(Span),
}

impl GenericArgs {
@@ -187,6 +189,7 @@ impl GenericArgs {
match self {
AngleBracketed(data) => data.span,
Parenthesized(data) => data.span,
ParenthesizedElided(span) => *span,
}
}
}
@@ -2051,7 +2054,7 @@ impl UintTy {
/// * the `A: Bound` in `Trait<A: Bound>`
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
/// * the `f(..): Bound` in `Trait<f(..): Bound>` (feature `return_type_notation`)
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct AssocItemConstraint {
pub id: NodeId,
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
@@ -582,6 +582,7 @@ fn noop_visit_generic_args<T: MutVisitor>(generic_args: &mut GenericArgs, vis: &
match generic_args {
GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data),
GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data),
GenericArgs::ParenthesizedElided(span) => vis.visit_span(span),
}
}

2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
@@ -234,6 +234,6 @@ fn path_return_type(path: &ast::Path) -> Option<&ast::Ty> {
ast::FnRetTy::Default(_) => None,
ast::FnRetTy::Ty(ret) => Some(ret),
},
ast::GenericArgs::AngleBracketed(_) => None,
ast::GenericArgs::AngleBracketed(_) | ast::GenericArgs::ParenthesizedElided(_) => None,
}
}
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
@@ -609,6 +609,7 @@ where
walk_list!(visitor, visit_ty, inputs);
try_visit!(visitor.visit_fn_ret_ty(output));
}
GenericArgs::ParenthesizedElided(_span) => {}
}
V::Result::output()
}
5 changes: 5 additions & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
@@ -36,10 +36,15 @@ ast_lowering_bad_return_type_notation_inputs =
argument types not allowed with return type notation
.suggestion = remove the input types

ast_lowering_bad_return_type_notation_needs_dots = return type notation arguments must be elided with `..`
.suggestion = add `..`

ast_lowering_bad_return_type_notation_output =
return type not allowed with return type notation
.suggestion = remove the return type

ast_lowering_bad_return_type_notation_position = return type notation not allowed in this position yet

ast_lowering_base_expression_double_dot =
base expression required after `..`
.suggestion = add a base expression here
11 changes: 11 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
@@ -393,6 +393,17 @@ pub enum BadReturnTypeNotation {
#[suggestion(code = "", applicability = "maybe-incorrect")]
span: Span,
},
#[diag(ast_lowering_bad_return_type_notation_needs_dots)]
NeedsDots {
#[primary_span]
#[suggestion(code = "(..)", applicability = "maybe-incorrect")]
span: Span,
},
#[diag(ast_lowering_bad_return_type_notation_position)]
Position {
#[primary_span]
span: Span,
},
}

#[derive(Diagnostic)]
25 changes: 10 additions & 15 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -979,20 +979,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
}
GenericArgs::Parenthesized(data) => {
if data.inputs.is_empty() && matches!(data.output, FnRetTy::Default(..)) {
let parenthesized = if self.tcx.features().return_type_notation {
hir::GenericArgsParentheses::ReturnTypeNotation
} else {
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
hir::GenericArgsParentheses::No
};
GenericArgsCtor {
args: Default::default(),
constraints: &[],
parenthesized,
span: data.inputs_span,
}
} else if let Some(first_char) = constraint.ident.as_str().chars().next()
if let Some(first_char) = constraint.ident.as_str().chars().next()
&& first_char.is_ascii_lowercase()
{
let mut err = if !data.inputs.is_empty() {
@@ -1004,7 +991,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: data.inputs_span.shrink_to_hi().to(ty.span),
})
} else {
unreachable!("inputs are empty and return type is not provided")
self.dcx().create_err(errors::BadReturnTypeNotation::NeedsDots {
span: data.inputs_span,
})
};
if !self.tcx.features().return_type_notation
&& self.tcx.sess.is_nightly_build()
@@ -1034,6 +1023,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.0
}
}
GenericArgs::ParenthesizedElided(span) => GenericArgsCtor {
args: Default::default(),
constraints: &[],
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
span: *span,
},
};
gen_args_ctor.into_generic_args(self)
} else {
15 changes: 14 additions & 1 deletion compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::ImplTraitPosition;

use super::errors::{
AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, GenericTypeWithParentheses, UseAngleBrackets,
AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, BadReturnTypeNotation,
GenericTypeWithParentheses, UseAngleBrackets,
};
use super::ResolverAstLoweringExt;
use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
@@ -276,6 +277,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
}
},
GenericArgs::ParenthesizedElided(span) => {
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
(
GenericArgsCtor {
args: Default::default(),
constraints: &[],
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
span: *span,
},
false,
)
}
}
} else {
(
7 changes: 5 additions & 2 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
@@ -1289,6 +1289,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.with_impl_trait(None, |this| this.visit_ty(ty));
}
}
GenericArgs::ParenthesizedElided(_span) => {}
}
}

@@ -1445,7 +1446,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
span: args.span,
});
}
None => {}
Some(ast::GenericArgs::ParenthesizedElided(_)) | None => {}
}
}
}
@@ -1693,7 +1694,9 @@ fn deny_equality_constraints(
// Add `<Bar = RhsTy>` to `Foo`.
match &mut assoc_path.segments[len].args {
Some(args) => match args.deref_mut() {
GenericArgs::Parenthesized(_) => continue,
GenericArgs::Parenthesized(_) | GenericArgs::ParenthesizedElided(..) => {
continue;
}
GenericArgs::AngleBracketed(args) => {
args.args.push(arg);
}
24 changes: 2 additions & 22 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{attr, AssocItemConstraint, AssocItemConstraintKind, NodeId};
use rustc_ast::{attr, NodeId};
use rustc_ast::{token, PatKind};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
@@ -445,23 +445,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_fn(self, fn_kind)
}

fn visit_assoc_item_constraint(&mut self, constraint: &'a AssocItemConstraint) {
if let AssocItemConstraintKind::Bound { .. } = constraint.kind
&& let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref()
&& args.inputs.is_empty()
&& let ast::FnRetTy::Default(..) = args.output
{
gate!(
&self,
return_type_notation,
constraint.span,
"return type notation is experimental"
);
}

visit::walk_assoc_item_constraint(self, constraint)
}

fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
let is_fn = match &i.kind {
ast::AssocItemKind::Fn(_) => true,
@@ -566,6 +549,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
unsafe_extern_blocks,
"`unsafe extern {}` blocks and `safe` keyword are experimental"
);
gate_all!(return_type_notation, "return type notation is experimental");

if !visitor.features.never_patterns {
if let Some(spans) = spans.get(&sym::never_patterns) {
@@ -611,10 +595,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {

gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental");
gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental");
// Despite being a new feature, `where T: Trait<Assoc(): Sized>`, which is RTN syntax now,
// used to be gated under associated_type_bounds, which are right above, so RTN needs to
// be too.
gate_all_legacy_dont_use!(return_type_notation, "return type notation is experimental");
gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental");
gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable");
gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable");
5 changes: 5 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
@@ -1060,6 +1060,11 @@ impl<'a> PrintState<'a> for State<'a> {
self.word(")");
self.print_fn_ret_ty(&data.output);
}
ast::GenericArgs::ParenthesizedElided(_) => {
self.word("(");
self.word("..");
self.word(")");
}
}
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -2413,7 +2413,7 @@ pub enum ImplItemKind<'hir> {
/// * the `A: Bound` in `Trait<A: Bound>`
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
/// * the `f(..): Bound` in `Trait<f(..): Bound>` (feature `return_type_notation`)
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct AssocItemConstraint<'hir> {
pub hir_id: HirId,
4 changes: 0 additions & 4 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
@@ -45,10 +45,6 @@ parse_bad_assoc_type_bounds = bounds on associated types do not belong here
parse_bad_item_kind = {$descr} is not supported in {$ctx}
.help = consider moving the {$descr} out to a nearby module scope

parse_bad_return_type_notation_dotdot =
return type notation uses `()` instead of `(..)` for elided arguments
.suggestion = remove the `..`

parse_bad_return_type_notation_output =
return type not allowed with return type notation
.suggestion = remove the return type
8 changes: 0 additions & 8 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
@@ -2567,14 +2567,6 @@ pub(crate) struct BadReturnTypeNotationOutput {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_bad_return_type_notation_dotdot)]
pub(crate) struct BadReturnTypeNotationDotDot {
#[primary_span]
#[suggestion(code = "", applicability = "maybe-incorrect")]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_bad_assoc_type_bounds)]
pub(crate) struct BadAssocTypeBounds {
27 changes: 6 additions & 21 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
@@ -353,32 +353,25 @@ impl<'a> Parser<'a> {
})?;
let span = lo.to(self.prev_token.span);
AngleBracketedArgs { args, span }.into()
} else if self.may_recover()
&& self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
} else if self.token.kind == token::OpenDelim(Delimiter::Parenthesis)
// FIXME(return_type_notation): Could also recover `...` here.
&& self.look_ahead(1, |tok| tok.kind == token::DotDot)
{
self.bump();
self.dcx()
.emit_err(errors::BadReturnTypeNotationDotDot { span: self.token.span });
self.bump();
self.bump(); // (
self.bump(); // ..
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
let span = lo.to(self.prev_token.span);

self.psess.gated_spans.gate(sym::return_type_notation, span);

if self.eat_noexpect(&token::RArrow) {
let lo = self.prev_token.span;
let ty = self.parse_ty()?;
self.dcx()
.emit_err(errors::BadReturnTypeNotationOutput { span: lo.to(ty.span) });
}

ParenthesizedArgs {
span,
inputs: ThinVec::new(),
inputs_span: span,
output: ast::FnRetTy::Default(self.prev_token.span.shrink_to_hi()),
}
.into()
P(ast::GenericArgs::ParenthesizedElided(span))
} else {
// `(T, U) -> R`

@@ -733,14 +726,6 @@ impl<'a> Parser<'a> {

let span = lo.to(self.prev_token.span);

if let AssocItemConstraintKind::Bound { .. } = kind
&& let Some(ast::GenericArgs::Parenthesized(args)) = &gen_args
&& args.inputs.is_empty()
&& let ast::FnRetTy::Default(..) = args.output
{
self.psess.gated_spans.gate(sym::return_type_notation, span);
}

let constraint =
AssocItemConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
Ok(Some(AngleBracketedArg::Constraint(constraint)))
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/hir_stats.rs
Original file line number Diff line number Diff line change
@@ -695,7 +695,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn visit_generic_args(&mut self, g: &'v ast::GenericArgs) {
record_variants!(
(self, g, g, Id::None, ast, GenericArgs, GenericArgs),
[AngleBracketed, Parenthesized]
[AngleBracketed, Parenthesized, ParenthesizedElided]
);
ast_visit::walk_generic_args(self, g)
}
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
@@ -1221,6 +1221,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
}
}
}
GenericArgs::ParenthesizedElided(_) => {}
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
@@ -350,6 +350,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
(args.span, found_lifetimes)
}
GenericArgs::Parenthesized(args) => (args.span, true),
GenericArgs::ParenthesizedElided(span) => (*span, true),
}
} else {
(DUMMY_SP, false)
2 changes: 1 addition & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
@@ -2557,7 +2557,7 @@ pub(crate) struct ProcMacro {
/// * the `A: Bound` in `Trait<A: Bound>`
/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy`
/// * the `C = { Ct }` in `Trait<C = { Ct }>` (feature `associated_const_equality`)
/// * the `f(): Bound` in `Trait<f(): Bound>` (feature `return_type_notation`)
/// * the `f(..): Bound` in `Trait<f(..): Bound>` (feature `return_type_notation`)
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct AssocItemConstraint {
pub(crate) assoc: PathSegment,
Loading