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

Implement Return Type Notation (RTN)'s path form in where clauses #129629

Merged
merged 7 commits into from
Sep 22, 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: 3 additions & 2 deletions compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use super::errors::{
};
use super::LoweringContext;
use crate::{
fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode,
ResolverAstLoweringExt,
fluent_generated as fluent, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition,
ParamMode, ResolverAstLoweringExt,
};

impl<'a, 'hir> LoweringContext<'a, 'hir> {
Expand Down Expand Up @@ -201,6 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&sym.qself,
&sym.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use rustc_target::spec::abi;
use {rustc_ast as ast, rustc_hir as hir};

use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};

pub(crate) struct DelegationResults<'hir> {
pub body_id: hir::BodyId,
Expand Down Expand Up @@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&delegation.qself,
&delegation.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use super::{
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
};
use crate::errors::YieldInClosure;
use crate::{fluent_generated, FnDeclKind, ImplTraitPosition};
use crate::{fluent_generated, AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition};

impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
Expand Down Expand Up @@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down Expand Up @@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.qself,
&se.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
)),
Expand Down Expand Up @@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand All @@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand All @@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.qself,
&se.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down
27 changes: 26 additions & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,23 @@ enum ParamMode {
Optional,
}

#[derive(Copy, Clone, Debug)]
enum AllowReturnTypeNotation {
/// Only in types, since RTN is denied later during HIR lowering.
Yes,
/// All other positions (path expr, method, use tree).
No,
}

enum GenericArgsMode {
/// Allow paren sugar, don't allow RTN.
ParenSugar,
/// Allow RTN, don't allow paren sugar.
ReturnTypeNotation,
// Error if parenthesized generics or RTN are encountered.
Err,
/// Silence errors when lowering generics. Only used with `Res::Err`.
Silence,
}

impl<'a, 'hir> LoweringContext<'a, 'hir> {
Expand Down Expand Up @@ -1226,7 +1240,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

let id = self.lower_node_id(t.id);
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
let qpath = self.lower_qpath(
t.id,
qself,
path,
param_mode,
AllowReturnTypeNotation::Yes,
itctx,
None,
);
self.ty_path(id, t.span, qpath)
}

Expand Down Expand Up @@ -2203,6 +2225,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&None,
&p.path,
ParamMode::Explicit,
AllowReturnTypeNotation::No,
itctx,
Some(modifiers),
) {
Expand Down Expand Up @@ -2341,6 +2364,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&None,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down Expand Up @@ -2419,6 +2443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
};
use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
use crate::ImplTraitPosition;
use crate::{AllowReturnTypeNotation, ImplTraitPosition};

impl<'a, 'hir> LoweringContext<'a, 'hir> {
pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
Expand All @@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand All @@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand All @@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
Expand Down
80 changes: 69 additions & 11 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
use rustc_middle::span_bug;
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
Expand All @@ -15,10 +16,9 @@ use super::errors::{
GenericTypeWithParentheses, UseAngleBrackets,
};
use super::{
GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode,
ResolverAstLoweringExt,
AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
};
use crate::ImplTraitPosition;

impl<'a, 'hir> LoweringContext<'a, 'hir> {
#[instrument(level = "trace", skip(self))]
Expand All @@ -28,6 +28,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself: &Option<ptr::P<QSelf>>,
p: &Path,
param_mode: ParamMode,
allow_return_type_notation: AllowReturnTypeNotation,
itctx: ImplTraitContext,
// modifiers of the impl/bound if this is a trait path
modifiers: Option<ast::TraitBoundModifiers>,
Expand Down Expand Up @@ -103,8 +104,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
{
GenericArgsMode::ParenSugar
}
Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => {
match allow_return_type_notation {
AllowReturnTypeNotation::Yes => GenericArgsMode::ReturnTypeNotation,
AllowReturnTypeNotation::No => GenericArgsMode::Err,
}
}
// Avoid duplicated errors.
Res::Err => GenericArgsMode::ParenSugar,
Res::Err => GenericArgsMode::Silence,
// An error
_ => GenericArgsMode::Err,
};
Expand Down Expand Up @@ -164,11 +171,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
// If this is a type-dependent `T::method(..)`.
let generic_args_mode = if i + 1 == p.segments.len()
&& matches!(allow_return_type_notation, AllowReturnTypeNotation::Yes)
{
GenericArgsMode::ReturnTypeNotation
} else {
GenericArgsMode::Err
};

let hir_segment = self.arena.alloc(self.lower_path_segment(
p.span,
segment,
param_mode,
GenericArgsMode::Err,
generic_args_mode,
itctx,
None,
));
Expand Down Expand Up @@ -238,11 +254,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
}
GenericArgs::Parenthesized(data) => match generic_args_mode {
GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data(
data,
itctx,
bound_modifier_allowed_features,
),
GenericArgsMode::ReturnTypeNotation => {
let mut err = if !data.inputs.is_empty() {
self.dcx().create_err(BadReturnTypeNotation::Inputs {
span: data.inputs_span,
})
} else if let FnRetTy::Ty(ty) = &data.output {
self.dcx().create_err(BadReturnTypeNotation::Output {
span: data.inputs_span.shrink_to_hi().to(ty.span),
})
} else {
self.dcx().create_err(BadReturnTypeNotation::NeedsDots {
span: data.inputs_span,
})
};
if !self.tcx.features().return_type_notation
&& self.tcx.sess.is_nightly_build()
{
add_feature_diagnostics(
&mut err,
&self.tcx.sess,
sym::return_type_notation,
);
}
err.emit();
(
GenericArgsCtor {
args: Default::default(),
constraints: &[],
parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
span: path_span,
},
false,
)
}
GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self
.lower_parenthesized_parameter_data(
data,
itctx,
bound_modifier_allowed_features,
),
GenericArgsMode::Err => {
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
let sub = if !data.inputs.is_empty() {
Expand Down Expand Up @@ -279,7 +330,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
},
GenericArgs::ParenthesizedElided(span) => {
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
match generic_args_mode {
GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => {
// Ok
}
GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
}
}
(
GenericArgsCtor {
args: Default::default(),
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}

hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here

hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated {$what} of a trait with uninferred generic parameters
.suggestion = use a fully qualified path with inferred lifetimes

hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
Expand All @@ -48,6 +48,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh

hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}

hir_analysis_bad_return_type_notation_position = return type notation not allowed in this position yet

hir_analysis_cannot_capture_late_bound_const =
cannot capture late-bound const parameter in {$what}
.label = parameter defined here
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
[] => (generics.span, format!("<{lt_name}>")),
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
};
mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
fspan: lt_sp,
first: sugg,
sspan: span.with_hi(item_segment.ident.span.lo()),
Expand Down Expand Up @@ -502,11 +502,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
}
Ty::new_error(
self.tcx(),
self.tcx().dcx().emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
span,
inferred_sugg,
bound,
mpart_sugg,
what: "type",
}),
)
}
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
for predicate in hir_generics.predicates {
match predicate {
hir::WherePredicate::BoundPredicate(bound_pred) => {
let ty = icx.lower_ty(bound_pred.bounded_ty);
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);

let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
// Keep the type around in a dummy predicate, in case of no bounds.
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
Expand Down Expand Up @@ -770,6 +771,10 @@ impl<'tcx> ItemCtxt<'tcx> {
continue;
};

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

// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
// want to only consider predicates with `Self: ...`, but we don't want
// `OnlySelfBounds(true)` since we want to collect the nested associated
// type bound as well.
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
ty
} else if matches!(filter, PredicateFilter::All) {
self.lower_ty(predicate.bounded_ty)
self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty)
} else {
continue;
};
Expand Down
Loading
Loading