1
Fork 0

Conditionally allow lowering RTN (..) in paths

This commit is contained in:
Michael Goulet 2024-08-26 14:51:26 -04:00
parent 6d788a18c5
commit 19881b5a5a
13 changed files with 141 additions and 54 deletions

View file

@ -20,8 +20,8 @@ use super::errors::{
}; };
use super::LoweringContext; use super::LoweringContext;
use crate::{ use crate::{
fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode, fluent_generated as fluent, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition,
ResolverAstLoweringExt, ParamMode, ResolverAstLoweringExt,
}; };
impl<'a, 'hir> LoweringContext<'a, 'hir> { impl<'a, 'hir> LoweringContext<'a, 'hir> {
@ -201,6 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&sym.qself, &sym.qself,
&sym.path, &sym.path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );

View file

@ -52,7 +52,7 @@ use rustc_target::spec::abi;
use {rustc_ast as ast, rustc_hir as hir}; use {rustc_ast as ast, rustc_hir as hir};
use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
use crate::{ImplTraitPosition, ResolverAstLoweringExt}; use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
pub(crate) struct DelegationResults<'hir> { pub(crate) struct DelegationResults<'hir> {
pub body_id: hir::BodyId, pub body_id: hir::BodyId,
@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&delegation.qself, &delegation.qself,
&delegation.path, &delegation.path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );

View file

@ -23,7 +23,7 @@ use super::{
GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
}; };
use crate::errors::YieldInClosure; use crate::errors::YieldInClosure;
use crate::{fluent_generated, FnDeclKind, ImplTraitPosition}; use crate::{fluent_generated, AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition};
impl<'hir> LoweringContext<'_, 'hir> { impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.qself, &se.qself,
&se.path, &se.path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
)), )),
@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.qself, &se.qself,
&se.path, &se.path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );

View file

@ -485,8 +485,16 @@ enum ParamMode {
Optional, Optional,
} }
#[derive(Copy, Clone, Debug)]
enum AllowReturnTypeNotation {
Yes,
No,
}
#[derive(Copy, Clone, Debug)]
enum GenericArgsMode { enum GenericArgsMode {
ParenSugar, ParenSugar,
ReturnTypeNotation,
Err, Err,
} }
@ -1226,7 +1234,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
let id = self.lower_node_id(t.id); 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,
// We deny these after the fact in HIR->middle type lowering.
AllowReturnTypeNotation::Yes,
itctx,
None,
);
self.ty_path(id, t.span, qpath) self.ty_path(id, t.span, qpath)
} }
@ -2203,6 +2220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&None, &None,
&p.path, &p.path,
ParamMode::Explicit, ParamMode::Explicit,
AllowReturnTypeNotation::No,
itctx, itctx,
Some(modifiers), Some(modifiers),
) { ) {
@ -2341,6 +2359,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&None, &None,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
@ -2419,6 +2438,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );

View file

@ -11,7 +11,7 @@ use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
}; };
use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt}; use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
use crate::ImplTraitPosition; use crate::{AllowReturnTypeNotation, ImplTraitPosition};
impl<'a, 'hir> LoweringContext<'a, 'hir> { impl<'a, 'hir> LoweringContext<'a, 'hir> {
pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> { pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself, qself,
path, path,
ParamMode::Optional, ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );

View file

@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg; use rustc_hir::GenericArg;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_session::parse::add_feature_diagnostics;
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -15,8 +16,8 @@ use super::errors::{
GenericTypeWithParentheses, UseAngleBrackets, GenericTypeWithParentheses, UseAngleBrackets,
}; };
use super::{ use super::{
GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode, AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes,
ResolverAstLoweringExt, LoweringContext, ParamMode, ResolverAstLoweringExt,
}; };
use crate::ImplTraitPosition; use crate::ImplTraitPosition;
@ -28,6 +29,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself: &Option<ptr::P<QSelf>>, qself: &Option<ptr::P<QSelf>>,
p: &Path, p: &Path,
param_mode: ParamMode, param_mode: ParamMode,
allow_return_type_notation: AllowReturnTypeNotation,
itctx: ImplTraitContext, itctx: ImplTraitContext,
// modifiers of the impl/bound if this is a trait path // modifiers of the impl/bound if this is a trait path
modifiers: Option<ast::TraitBoundModifiers>, modifiers: Option<ast::TraitBoundModifiers>,
@ -103,6 +105,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
{ {
GenericArgsMode::ParenSugar 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. // Avoid duplicated errors.
Res::Err => GenericArgsMode::ParenSugar, Res::Err => GenericArgsMode::ParenSugar,
// An error // An error
@ -164,11 +172,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// 3. `<<std::vec::Vec<T>>::IntoIter>::Item` // 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
// * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone` // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
for (i, segment) in p.segments.iter().enumerate().skip(proj_start) { 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( let hir_segment = self.arena.alloc(self.lower_path_segment(
p.span, p.span,
segment, segment,
param_mode, param_mode,
GenericArgsMode::Err, generic_args_mode,
itctx, itctx,
None, None,
)); ));
@ -238,6 +255,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
} }
GenericArgs::Parenthesized(data) => match generic_args_mode { GenericArgs::Parenthesized(data) => match generic_args_mode {
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 => self.lower_parenthesized_parameter_data( GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data(
data, data,
itctx, itctx,
@ -279,7 +330,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
}, },
GenericArgs::ParenthesizedElided(span) => { GenericArgs::ParenthesizedElided(span) => {
match generic_args_mode {
GenericArgsMode::ReturnTypeNotation => {
// Ok
}
GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span }); self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
}
}
( (
GenericArgsCtor { GenericArgsCtor {
args: Default::default(), args: Default::default(),

View file

@ -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_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 = hir_analysis_cannot_capture_late_bound_const =
cannot capture late-bound const parameter in {$what} cannot capture late-bound const parameter in {$what}
.label = parameter defined here .label = parameter defined here

View file

@ -1693,3 +1693,10 @@ pub(crate) struct CmseCallGeneric {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[diag(hir_analysis_bad_return_type_notation_position)]
pub(crate) struct BadReturnTypeNotation {
#[primary_span]
pub span: Span,
}

View file

@ -53,7 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
use tracing::{debug, debug_span, instrument}; use tracing::{debug, debug_span, instrument};
use crate::bounds::Bounds; use crate::bounds::Bounds;
use crate::errors::{AmbiguousLifetimeBound, WildPatTy}; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy};
use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend}; use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
use crate::middle::resolve_bound_vars as rbv; use crate::middle::resolve_bound_vars as rbv;
@ -1910,6 +1910,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::BoundConstness::NotConst, ty::BoundConstness::NotConst,
) )
} }
// Deny any qpath types that were successfully lowered in AST lowering.
Res::Def(DefKind::AssocFn, _)
if let [.., _trait_segment, item_segment] = &path.segments[..]
&& item_segment.args.is_some_and(|args| {
matches!(
args.parenthesized,
hir::GenericArgsParentheses::ReturnTypeNotation
)
}) =>
{
let guar = self.dcx().emit_err(BadReturnTypeNotation { span: path.span });
Ty::new_error(tcx, guar)
}
Res::PrimTy(prim_ty) => { Res::PrimTy(prim_ty) => {
assert_eq!(opt_self_ty, None); assert_eq!(opt_self_ty, None);
let _ = self.prohibit_generic_args( let _ = self.prohibit_generic_args(

View file

@ -10,17 +10,14 @@ trait Tr {
fn foo<T: Tr>() fn foo<T: Tr>()
where where
T::method(..): Send, T::method(..): Send,
//~^ ERROR return type notation not allowed in this position yet //~^ ERROR expected type, found function
//~| ERROR expected type, found function
<T as Tr>::method(..): Send, <T as Tr>::method(..): Send,
//~^ ERROR return type notation not allowed in this position yet //~^ ERROR return type notation not allowed in this position yet
//~| ERROR expected associated type, found associated function `Tr::method`
{ {
let _ = T::CONST::(..); let _ = T::CONST::(..);
//~^ ERROR return type notation not allowed in this position yet //~^ ERROR return type notation not allowed in this position yet
let _: T::method(..); let _: T::method(..);
//~^ ERROR return type notation not allowed in this position yet //~^ ERROR expected type, found function
//~| ERROR expected type, found function
} }
fn main() {} fn main() {}

View file

@ -1,9 +1,3 @@
error[E0575]: expected associated type, found associated function `Tr::method`
--> $DIR/bare-path.rs:15:5
|
LL | <T as Tr>::method(..): Send,
| ^^^^^^^^^^^^^^^^^^^^^ not a associated type
warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/bare-path.rs:1:12 --> $DIR/bare-path.rs:1:12
| |
@ -14,29 +8,11 @@ LL | #![feature(return_type_notation)]
= note: `#[warn(incomplete_features)]` on by default = note: `#[warn(incomplete_features)]` on by default
error: return type notation not allowed in this position yet error: return type notation not allowed in this position yet
--> $DIR/bare-path.rs:19:23 --> $DIR/bare-path.rs:17:23
| |
LL | let _ = T::CONST::(..); LL | let _ = T::CONST::(..);
| ^^^^ | ^^^^
error: return type notation not allowed in this position yet
--> $DIR/bare-path.rs:21:21
|
LL | let _: T::method(..);
| ^^^^
error: return type notation not allowed in this position yet
--> $DIR/bare-path.rs:12:14
|
LL | T::method(..): Send,
| ^^^^
error: return type notation not allowed in this position yet
--> $DIR/bare-path.rs:15:22
|
LL | <T as Tr>::method(..): Send,
| ^^^^
error: expected type, found function error: expected type, found function
--> $DIR/bare-path.rs:12:8 --> $DIR/bare-path.rs:12:8
| |
@ -49,8 +25,14 @@ note: the associated function is defined here
LL | fn method() -> impl Sized; LL | fn method() -> impl Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: return type notation not allowed in this position yet
--> $DIR/bare-path.rs:14:5
|
LL | <T as Tr>::method(..): Send,
| ^^^^^^^^^^^^^^^^^^^^^
error: expected type, found function error: expected type, found function
--> $DIR/bare-path.rs:21:15 --> $DIR/bare-path.rs:19:15
| |
LL | let _: T::method(..); LL | let _: T::method(..);
| ^^^^^^ unexpected function | ^^^^^^ unexpected function
@ -61,6 +43,5 @@ note: the associated function is defined here
LL | fn method() -> impl Sized; LL | fn method() -> impl Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 7 previous errors; 1 warning emitted error: aborting due to 4 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0575`.

View file

@ -1,7 +1,7 @@
pub fn foo(num: i32) -> i32 { pub fn foo(num: i32) -> i32 {
let foo: i32::from_be(num); let foo: i32::from_be(num);
//~^ ERROR expected type, found local variable `num` //~^ ERROR expected type, found local variable `num`
//~| ERROR parenthesized type parameters may only be used with a `Fn` trait //~| ERROR argument types not allowed with return type notation
//~| ERROR ambiguous associated type //~| ERROR ambiguous associated type
foo foo
} }

View file

@ -6,16 +6,15 @@ LL | let foo: i32::from_be(num);
| | | |
| help: use `=` if you meant to assign | help: use `=` if you meant to assign
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait error: argument types not allowed with return type notation
--> $DIR/let-binding-init-expr-as-ty.rs:2:19 --> $DIR/let-binding-init-expr-as-ty.rs:2:26
| |
LL | let foo: i32::from_be(num); LL | let foo: i32::from_be(num);
| ^^^^^^^^^^^^ only `Fn` traits may use parentheses | ^^^^^ help: remove the input types: `()`
| |
help: use angle brackets instead = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
| = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
LL | let foo: i32::from_be<num>; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
| ~ ~
error[E0223]: ambiguous associated type error[E0223]: ambiguous associated type
--> $DIR/let-binding-init-expr-as-ty.rs:2:14 --> $DIR/let-binding-init-expr-as-ty.rs:2:14
@ -30,5 +29,5 @@ LL | let foo: <i32 as Example>::from_be;
error: aborting due to 3 previous errors error: aborting due to 3 previous errors
Some errors have detailed explanations: E0214, E0223, E0573. Some errors have detailed explanations: E0223, E0573.
For more information about an error, try `rustc --explain E0214`. For more information about an error, try `rustc --explain E0223`.