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

View File

@ -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,
@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&delegation.qself,
&delegation.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

View File

@ -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>] {
@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.qself,
&se.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
)),
@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.qself,
&se.path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

View File

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

View File

@ -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> {
@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);

View File

@ -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};
@ -15,8 +16,8 @@ use super::errors::{
GenericTypeWithParentheses, UseAngleBrackets,
};
use super::{
GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode,
ResolverAstLoweringExt,
AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes,
LoweringContext, ParamMode, ResolverAstLoweringExt,
};
use crate::ImplTraitPosition;
@ -28,6 +29,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>,
@ -103,6 +105,12 @@ 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,
// An error
@ -164,11 +172,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,
));
@ -238,6 +255,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
}
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(
data,
itctx,
@ -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 => {
// Ok
}
GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
}
}
(
GenericArgsCtor {
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_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

View File

@ -1693,3 +1693,10 @@ pub(crate) struct CmseCallGeneric {
#[primary_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 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::generics::{check_generic_arg_count, lower_generic_args};
use crate::middle::resolve_bound_vars as rbv;
@ -1910,6 +1910,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
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) => {
assert_eq!(opt_self_ty, None);
let _ = self.prohibit_generic_args(

View File

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

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
--> $DIR/bare-path.rs:1:12
|
@ -14,29 +8,11 @@ LL | #![feature(return_type_notation)]
= note: `#[warn(incomplete_features)]` on by default
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::(..);
| ^^^^
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
--> $DIR/bare-path.rs:12:8
|
@ -49,8 +25,14 @@ note: the associated function is defined here
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
--> $DIR/bare-path.rs:21:15
--> $DIR/bare-path.rs:19:15
|
LL | let _: T::method(..);
| ^^^^^^ unexpected function
@ -61,6 +43,5 @@ note: the associated function is defined here
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 {
let foo: i32::from_be(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
foo
}

View File

@ -6,16 +6,15 @@ LL | let foo: i32::from_be(num);
| |
| help: use `=` if you meant to assign
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/let-binding-init-expr-as-ty.rs:2:19
error: argument types not allowed with return type notation
--> $DIR/let-binding-init-expr-as-ty.rs:2:26
|
LL | let foo: i32::from_be(num);
| ^^^^^^^^^^^^ only `Fn` traits may use parentheses
| ^^^^^ help: remove the input types: `()`
|
help: use angle brackets instead
|
LL | let foo: i32::from_be<num>;
| ~ ~
= 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0223]: ambiguous associated type
--> $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
Some errors have detailed explanations: E0214, E0223, E0573.
For more information about an error, try `rustc --explain E0214`.
Some errors have detailed explanations: E0223, E0573.
For more information about an error, try `rustc --explain E0223`.