Skip to content
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

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

Merged
merged 3 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
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
Expand Up @@ -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 {
Expand All @@ -187,6 +189,7 @@ impl GenericArgs {
match self {
AngleBracketed(data) => data.span,
Parenthesized(data) => data.span,
ParenthesizedElided(span) => *span,
}
}
}
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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()
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
25 changes: 10 additions & 15 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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()
Expand Down Expand Up @@ -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 {
Expand Down
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};
Expand Down Expand Up @@ -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 {
(
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.with_impl_trait(None, |this| this.visit_ty(ty));
}
}
GenericArgs::ParenthesizedElided(_span) => {}
}
}

Expand Down Expand Up @@ -1445,7 +1446,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
span: args.span,
});
}
None => {}
Some(ast::GenericArgs::ParenthesizedElided(_)) | None => {}
}
}
}
Expand Down Expand Up @@ -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);
}
Expand Down
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};
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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");
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(")");
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_parse/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
27 changes: 6 additions & 21 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down Expand Up @@ -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)))
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/hir_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
}
}
}
GenericArgs::ParenthesizedElided(_) => {}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading