Skip to content

Provide more context on resolve error caused from incorrect RTN #137825

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 1 commit into from
Mar 7, 2025
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
1 change: 0 additions & 1 deletion compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
if let Some(first_char) = constraint.ident.as_str().chars().next()
&& first_char.is_ascii_lowercase()
{
tracing::info!(?data, ?data.inputs);
let err = match (&data.inputs[..], &data.output) {
([_, ..], FnRetTy::Default(_)) => {
errors::BadReturnTypeNotation::Inputs { span: data.inputs_span }
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
GenericArgs::Parenthesized(data) => match generic_args_mode {
GenericArgsMode::ReturnTypeNotation => {
tracing::info!(?data, ?data.inputs);
let err = match (&data.inputs[..], &data.output) {
([_, ..], FnRetTy::Default(_)) => {
BadReturnTypeNotation::Inputs { span: data.inputs_span }
Expand Down
18 changes: 15 additions & 3 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ pub(crate) struct UnnecessaryQualification<'ra> {
pub removal_span: Span,
}

#[derive(Default)]
#[derive(Default, Debug)]
struct DiagMetadata<'ast> {
/// The current trait's associated items' ident, used for diagnostic suggestions.
current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,
Expand Down Expand Up @@ -3146,6 +3146,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
PathSource::Trait(AliasPossibility::No),
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
RecordPartialRes::Yes,
None,
);
self.diag_metadata.currently_processing_impl_trait = None;
if let Some(def_id) = res.expect_full_res().opt_def_id() {
Expand Down Expand Up @@ -4072,6 +4073,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
source,
Finalize::new(id, path.span),
RecordPartialRes::Yes,
None,
);
}

Expand All @@ -4083,14 +4085,21 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
source: PathSource<'ast>,
finalize: Finalize,
record_partial_res: RecordPartialRes,
parent_qself: Option<&QSelf>,
) -> PartialRes {
let ns = source.namespace();

let Finalize { node_id, path_span, .. } = finalize;
let report_errors = |this: &mut Self, res: Option<Res>| {
if this.should_report_errs() {
let (err, candidates) =
this.smart_resolve_report_errors(path, None, path_span, source, res);
let (err, candidates) = this.smart_resolve_report_errors(
path,
None,
path_span,
source,
res,
parent_qself,
);

let def_id = this.parent_scope.module.nearest_parent_mod();
let instead = res.is_some();
Expand Down Expand Up @@ -4159,6 +4168,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
path_span,
PathSource::Type,
None,
parent_qself,
);

// There are two different error messages user might receive at
Expand Down Expand Up @@ -4436,6 +4446,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
PathSource::Trait(AliasPossibility::No),
Finalize::new(finalize.node_id, qself.path_span),
RecordPartialRes::No,
Some(&qself),
);

if trait_res.expect_full_res() == Res::Err {
Expand All @@ -4460,6 +4471,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
PathSource::TraitItem(ns),
Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
RecordPartialRes::No,
Some(&qself),
);

// The remaining segments (the `C` in our example) will
Expand Down
39 changes: 38 additions & 1 deletion compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use super::NoConstantGenericsReason;
use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
use crate::late::{
AliasPossibility, LateResolutionVisitor, LifetimeBinderKind, LifetimeRes, LifetimeRibKind,
LifetimeUseSet, RibKind,
LifetimeUseSet, QSelf, RibKind,
};
use crate::ty::fast_reject::SimplifiedType;
use crate::{
Expand Down Expand Up @@ -421,6 +421,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
span: Span,
source: PathSource<'_>,
res: Option<Res>,
qself: Option<&QSelf>,
) -> (Diag<'tcx>, Vec<ImportSuggestion>) {
debug!(?res, ?source);
let base_error = self.make_base_error(path, span, source, res);
Expand Down Expand Up @@ -453,6 +454,15 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {

self.suggest_self_or_self_ref(&mut err, path, span);
self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error);
self.detect_rtn_with_fully_qualified_path(
&mut err,
path,
following_seg,
span,
source,
res,
qself,
);
if self.suggest_self_ty(&mut err, source, path, span)
|| self.suggest_self_value(&mut err, source, path, span)
{
Expand Down Expand Up @@ -501,6 +511,33 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
(err, candidates)
}

fn detect_rtn_with_fully_qualified_path(
&self,
err: &mut Diag<'_>,
path: &[Segment],
following_seg: Option<&Segment>,
span: Span,
source: PathSource<'_>,
res: Option<Res>,
qself: Option<&QSelf>,
) {
if let Some(Res::Def(DefKind::AssocFn, _)) = res
&& let PathSource::TraitItem(TypeNS) = source
&& let None = following_seg
&& let Some(qself) = qself
&& let TyKind::Path(None, ty_path) = &qself.ty.kind
&& ty_path.segments.len() == 1
&& self.diag_metadata.current_where_predicate.is_some()
{
err.span_suggestion_verbose(
span,
"you might have meant to use the return type notation syntax",
format!("{}::{}(..)", ty_path.segments[0].ident, path[path.len() - 1].ident),
Applicability::MaybeIncorrect,
);
}
}

fn detect_assoc_type_constraint_meant_as_path(
&self,
err: &mut Diag<'_>,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//@ edition: 2021
//@ run-rustfix
#![feature(return_type_notation)]
#![allow(dead_code)]

trait Trait {
async fn method() {}
}

fn foo<T: Trait<method(..): Send>>() {}
//~^ ERROR argument types not allowed with return type notation

fn bar<T: Trait<method(..): Send>>() {}
//~^ ERROR return type not allowed with return type notation

fn baz<T: Trait<method(..): Send>>() {}
//~^ ERROR return type notation arguments must be elided with `..`

fn foo_path<T: Trait>() where T::method(..): Send {}
//~^ ERROR argument types not allowed with return type notation

fn bar_path<T: Trait>() where T::method(..): Send {}
//~^ ERROR return type not allowed with return type notation

fn bay_path<T: Trait>() where T::method(..): Send {}
//~^ ERROR return type not allowed with return type notation

fn baz_path<T: Trait>() where T::method(..): Send {}
//~^ ERROR return type notation arguments must be elided with `..`

fn foo_qualified<T: Trait>() where T::method(..): Send {}
//~^ ERROR expected associated type

fn bar_qualified<T: Trait>() where T::method(..): Send {}
//~^ ERROR expected associated type

fn baz_qualified<T: Trait>() where T::method(..): Send {}
//~^ ERROR expected associated type

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ edition: 2021

//@ run-rustfix
#![feature(return_type_notation)]
#![allow(dead_code)]

trait Trait {
async fn method() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: return type not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:24:45
--> $DIR/bad-inputs-and-output.rs:25:45
|
LL | fn bay_path<T: Trait>() where T::method(..) -> (): Send {}
| ^^^^^
Expand All @@ -11,25 +11,43 @@ LL + fn bay_path<T: Trait>() where T::method(..): Send {}
|

error[E0575]: expected associated type, found associated function `Trait::method`
--> $DIR/bad-inputs-and-output.rs:30:36
--> $DIR/bad-inputs-and-output.rs:31:36
|
LL | fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
|
help: you might have meant to use the return type notation syntax
|
LL - fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
LL + fn foo_qualified<T: Trait>() where T::method(..): Send {}
|

error[E0575]: expected associated type, found associated function `Trait::method`
--> $DIR/bad-inputs-and-output.rs:33:36
--> $DIR/bad-inputs-and-output.rs:34:36
|
LL | fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
|
help: you might have meant to use the return type notation syntax
|
LL - fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
LL + fn bar_qualified<T: Trait>() where T::method(..): Send {}
|

error[E0575]: expected associated type, found associated function `Trait::method`
--> $DIR/bad-inputs-and-output.rs:36:36
--> $DIR/bad-inputs-and-output.rs:37:36
|
LL | fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
| ^^^^^^^^^^^^^^^^^^^^^^ not a associated type
|
help: you might have meant to use the return type notation syntax
|
LL - fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
LL + fn baz_qualified<T: Trait>() where T::method(..): Send {}
|

error: argument types not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:9:23
--> $DIR/bad-inputs-and-output.rs:10:23
|
LL | fn foo<T: Trait<method(i32): Send>>() {}
| ^^^^^
Expand All @@ -41,7 +59,7 @@ LL + fn foo<T: Trait<method(..): Send>>() {}
|

error: return type not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:12:25
--> $DIR/bad-inputs-and-output.rs:13:25
|
LL | fn bar<T: Trait<method() -> (): Send>>() {}
| ^^^^^^
Expand All @@ -53,7 +71,7 @@ LL + fn bar<T: Trait<method(..): Send>>() {}
|

error: return type notation arguments must be elided with `..`
--> $DIR/bad-inputs-and-output.rs:15:23
--> $DIR/bad-inputs-and-output.rs:16:23
|
LL | fn baz<T: Trait<method(): Send>>() {}
| ^^
Expand All @@ -64,7 +82,7 @@ LL | fn baz<T: Trait<method(..): Send>>() {}
| ++

error: argument types not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:18:40
--> $DIR/bad-inputs-and-output.rs:19:40
|
LL | fn foo_path<T: Trait>() where T::method(i32): Send {}
| ^^^^^
Expand All @@ -76,7 +94,7 @@ LL + fn foo_path<T: Trait>() where T::method(..): Send {}
|

error: return type not allowed with return type notation
--> $DIR/bad-inputs-and-output.rs:21:42
--> $DIR/bad-inputs-and-output.rs:22:42
|
LL | fn bar_path<T: Trait>() where T::method() -> (): Send {}
| ^^^^^^
Expand All @@ -88,7 +106,7 @@ LL + fn bar_path<T: Trait>() where T::method(..): Send {}
|

error: return type notation arguments must be elided with `..`
--> $DIR/bad-inputs-and-output.rs:27:40
--> $DIR/bad-inputs-and-output.rs:28:40
|
LL | fn baz_path<T: Trait>() where T::method(): Send {}
| ^^
Expand Down
Loading