From 26bdfefae121061187a8206bc0d6702c968a62c0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 15 Sep 2024 17:14:49 -0400 Subject: [PATCH 1/2] Do precise capturing arg validation in resolve --- .../src/collect/resolve_bound_vars.rs | 10 ++-- compiler/rustc_resolve/src/late.rs | 46 ++++++++++++++++--- .../rustc_resolve/src/late/diagnostics.rs | 9 +++- tests/crashes/130399.rs | 5 -- .../precise-capturing/bad-params.rs | 9 ++-- .../precise-capturing/bad-params.stderr | 26 +++++++---- 6 files changed, 72 insertions(+), 33 deletions(-) delete mode 100644 tests/crashes/130399.rs diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index b4cbd1f309c97..53dcede91c36a 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -584,7 +584,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | Res::SelfTyParam { trait_: def_id } => { self.resolve_type_ref(def_id.expect_local(), param.hir_id); } - Res::Err => {} Res::SelfTyAlias { alias_to, .. } => { self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias { span: param.ident.span, @@ -593,11 +592,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }); } res => { - self.tcx.dcx().emit_err(errors::BadPreciseCapture { - span: param.ident.span, - kind: "type or const", - found: res.descr().to_string(), - }); + self.tcx.dcx().span_delayed_bug( + param.ident.span, + format!("expected type or const param, found {res:?}"), + ); } }, } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0aa351cad4043..148f55986bacd 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -402,6 +402,8 @@ pub(crate) enum PathSource<'a> { TraitItem(Namespace), // Paths in delegation item Delegation, + /// An arg in a `use<'a, N>` precise-capturing bound. + PreciseCapturingArg(Namespace), } impl<'a> PathSource<'a> { @@ -413,6 +415,7 @@ impl<'a> PathSource<'a> { | PathSource::TupleStruct(..) | PathSource::Delegation => ValueNS, PathSource::TraitItem(ns) => ns, + PathSource::PreciseCapturingArg(ns) => ns, } } @@ -423,7 +426,10 @@ impl<'a> PathSource<'a> { | PathSource::Pat | PathSource::Struct | PathSource::TupleStruct(..) => true, - PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation => false, + PathSource::Trait(_) + | PathSource::TraitItem(..) + | PathSource::Delegation + | PathSource::PreciseCapturingArg(..) => false, } } @@ -466,6 +472,7 @@ impl<'a> PathSource<'a> { _ => "value", }, PathSource::Delegation => "function", + PathSource::PreciseCapturingArg(..) => "type or const parameter", } } @@ -534,6 +541,15 @@ impl<'a> PathSource<'a> { _ => false, }, PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)), + PathSource::PreciseCapturingArg(ValueNS) => { + matches!(res, Res::Def(DefKind::ConstParam, _)) + } + // We allow `SelfTyAlias` here so we can give a more descriptive error later. + PathSource::PreciseCapturingArg(TypeNS) => matches!( + res, + Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } + ), + PathSource::PreciseCapturingArg(MacroNS) => false, } } @@ -541,8 +557,9 @@ impl<'a> PathSource<'a> { match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => E0404, (PathSource::Trait(_), false) => E0405, - (PathSource::Type, true) => E0573, - (PathSource::Type, false) => E0412, + // TODO: + (PathSource::Type | PathSource::PreciseCapturingArg(..), true) => E0573, + (PathSource::Type | PathSource::PreciseCapturingArg(..), false) => E0412, (PathSource::Struct, true) => E0574, (PathSource::Struct, false) => E0422, (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423, @@ -1077,9 +1094,19 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r }; // Like `Ty::Param`, we try resolving this as both a const and a type. if !check_ns(TypeNS) && check_ns(ValueNS) { - self.smart_resolve_path(*id, &None, path, PathSource::Expr(None)); + self.smart_resolve_path( + *id, + &None, + path, + PathSource::PreciseCapturingArg(ValueNS), + ); } else { - self.smart_resolve_path(*id, &None, path, PathSource::Type); + self.smart_resolve_path( + *id, + &None, + path, + PathSource::PreciseCapturingArg(TypeNS), + ); } } } @@ -1889,7 +1916,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); let inferred = match source { - PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type => false, + PathSource::Trait(..) + | PathSource::TraitItem(..) + | PathSource::Type + | PathSource::PreciseCapturingArg(..) => false, PathSource::Expr(..) | PathSource::Pat | PathSource::Struct @@ -3982,7 +4012,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, )) } else if res.is_none() - && let PathSource::Type | PathSource::Expr(_) = source + && let PathSource::Type + | PathSource::Expr(_) + | PathSource::PreciseCapturingArg(..) = source { this.suggest_adding_generic_parameter(path, source) } else { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 1c584bf833862..676b242fda15b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2538,8 +2538,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } let (msg, sugg) = match source { - PathSource::Type => ("you might be missing a type parameter", ident), - PathSource::Expr(_) => ("you might be missing a const parameter", format!("const {ident}: /* Type */")), + PathSource::Type | PathSource::PreciseCapturingArg(TypeNS) => { + ("you might be missing a type parameter", ident) + } + PathSource::Expr(_) | PathSource::PreciseCapturingArg(ValueNS) => ( + "you might be missing a const parameter", + format!("const {ident}: /* Type */"), + ), _ => return None, }; let (span, sugg) = if let [.., param] = &generics.params[..] { diff --git a/tests/crashes/130399.rs b/tests/crashes/130399.rs deleted file mode 100644 index 2248c8c0124a9..0000000000000 --- a/tests/crashes/130399.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: rust-lang/rust#130399 - -fn elided(main: &()) -> impl Sized + use
{} - -fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.rs b/tests/ui/impl-trait/precise-capturing/bad-params.rs index 17b517abd74e4..d1ec48df48c7b 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.rs +++ b/tests/ui/impl-trait/precise-capturing/bad-params.rs @@ -1,8 +1,8 @@ fn missing() -> impl Sized + use {} -//~^ ERROR cannot find type `T` in this scope +//~^ ERROR cannot find type or const parameter `T` in this scope fn missing_self() -> impl Sized + use {} -//~^ ERROR cannot find type `Self` in this scope +//~^ ERROR cannot find type or const parameter `Self` in this scope struct MyType; impl MyType { @@ -11,6 +11,9 @@ impl MyType { } fn hello() -> impl Sized + use {} -//~^ ERROR expected type or const parameter in `use<...>` precise captures list, found function +//~^ ERROR expected type or const parameter, found function `hello` + +fn arg(x: ()) -> impl Sized + use {} +//~^ ERROR expected type or const parameter, found local variable `x` fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.stderr b/tests/ui/impl-trait/precise-capturing/bad-params.stderr index 06ccf35694811..94577881d6c3b 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.stderr +++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr @@ -1,4 +1,4 @@ -error[E0412]: cannot find type `T` in this scope +error[E0412]: cannot find type or const parameter `T` in this scope --> $DIR/bad-params.rs:1:34 | LL | fn missing() -> impl Sized + use {} @@ -9,7 +9,7 @@ help: you might be missing a type parameter LL | fn missing() -> impl Sized + use {} | +++ -error[E0411]: cannot find type `Self` in this scope +error[E0411]: cannot find type or const parameter `Self` in this scope --> $DIR/bad-params.rs:4:39 | LL | fn missing_self() -> impl Sized + use {} @@ -17,6 +17,18 @@ LL | fn missing_self() -> impl Sized + use {} | | | `Self` not allowed in a function +error[E0573]: expected type or const parameter, found function `hello` + --> $DIR/bad-params.rs:13:32 + | +LL | fn hello() -> impl Sized + use {} + | ^^^^^ not a type or const parameter + +error[E0573]: expected type or const parameter, found local variable `x` + --> $DIR/bad-params.rs:16:35 + | +LL | fn arg(x: ()) -> impl Sized + use {} + | ^ not a type or const parameter + error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias --> $DIR/bad-params.rs:9:48 | @@ -25,13 +37,7 @@ LL | impl MyType { LL | fn self_is_not_param() -> impl Sized + use {} | ^^^^ -error: expected type or const parameter in `use<...>` precise captures list, found function - --> $DIR/bad-params.rs:13:32 - | -LL | fn hello() -> impl Sized + use {} - | ^^^^^ - -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0411, E0412. +Some errors have detailed explanations: E0411, E0412, E0573. For more information about an error, try `rustc --explain E0411`. From ae8b4607c6c92164dce2e92f9496de189a43bc44 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 15 Sep 2024 17:34:25 -0400 Subject: [PATCH 2/2] Introduce distinct error codes for precise capturing --- .../src/error_codes/E0799.md | 19 +++++++++++++++++++ .../src/error_codes/E0800.md | 11 +++++++++++ compiler/rustc_error_codes/src/lib.rs | 2 ++ .../src/errors/precise_captures.rs | 3 ++- compiler/rustc_resolve/src/late.rs | 7 ++++--- tests/ui/error-codes/E0799.rs | 4 ++++ tests/ui/error-codes/E0799.stderr | 9 +++++++++ tests/ui/error-codes/E0800.rs | 4 ++++ tests/ui/error-codes/E0800.stderr | 9 +++++++++ .../precise-capturing/bad-params.stderr | 10 +++++----- 10 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0799.md create mode 100644 compiler/rustc_error_codes/src/error_codes/E0800.md create mode 100644 tests/ui/error-codes/E0799.rs create mode 100644 tests/ui/error-codes/E0799.stderr create mode 100644 tests/ui/error-codes/E0800.rs create mode 100644 tests/ui/error-codes/E0800.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0799.md b/compiler/rustc_error_codes/src/error_codes/E0799.md new file mode 100644 index 0000000000000..38ebc84060497 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0799.md @@ -0,0 +1,19 @@ +Something other than a type or const parameter has been used when one was +expected. + +Erroneous code example: + +```compile_fail,E0799 +fn bad1() -> impl Sized + use
{} + +fn bad2(x: ()) -> impl Sized + use {} + +fn main() {} +``` + +In the given examples, for `bad1`, the name `main` corresponds to a function +rather than a type or const parameter. In `bad2`, the name `x` corresponds to +a function argument rather than a type or const parameter. + +Only type and const parameters, including `Self`, may be captured by +`use<...>` precise capturing bounds. diff --git a/compiler/rustc_error_codes/src/error_codes/E0800.md b/compiler/rustc_error_codes/src/error_codes/E0800.md new file mode 100644 index 0000000000000..3e08cd499b7e6 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0800.md @@ -0,0 +1,11 @@ +A type or const parameter of the given name is not in scope. + +Erroneous code examples: + +```compile_fail,E0800 +fn missing() -> impl Sized + use {} +``` + +To fix this error, please verify you didn't misspell the type or const +parameter, or double-check if you forgot to declare the parameter in +the list of generics. diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 150f99a3ee743..d6f0206b0de0a 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -538,6 +538,8 @@ E0795: 0795, E0796: 0796, E0797: 0797, E0798: 0798, +E0799: 0799, +E0800: 0800, ); ) } diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs index af2bb053c0ab4..b6cffb90805b3 100644 --- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs +++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs @@ -1,3 +1,4 @@ +use rustc_errors::E0799; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -43,7 +44,7 @@ pub(crate) struct BadPreciseCapture { } #[derive(Diagnostic)] -#[diag(hir_analysis_precise_capture_self_alias)] +#[diag(hir_analysis_precise_capture_self_alias, code = E0799)] pub(crate) struct PreciseCaptureSelfAlias { #[primary_span] pub span: Span, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 148f55986bacd..4bf2cc287daae 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -557,9 +557,8 @@ impl<'a> PathSource<'a> { match (self, has_unexpected_resolution) { (PathSource::Trait(_), true) => E0404, (PathSource::Trait(_), false) => E0405, - // TODO: - (PathSource::Type | PathSource::PreciseCapturingArg(..), true) => E0573, - (PathSource::Type | PathSource::PreciseCapturingArg(..), false) => E0412, + (PathSource::Type, true) => E0573, + (PathSource::Type, false) => E0412, (PathSource::Struct, true) => E0574, (PathSource::Struct, false) => E0422, (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423, @@ -568,6 +567,8 @@ impl<'a> PathSource<'a> { (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531, (PathSource::TraitItem(..), true) => E0575, (PathSource::TraitItem(..), false) => E0576, + (PathSource::PreciseCapturingArg(..), true) => E0799, + (PathSource::PreciseCapturingArg(..), false) => E0800, } } } diff --git a/tests/ui/error-codes/E0799.rs b/tests/ui/error-codes/E0799.rs new file mode 100644 index 0000000000000..a1e5b5326691f --- /dev/null +++ b/tests/ui/error-codes/E0799.rs @@ -0,0 +1,4 @@ +fn test() -> impl Sized + use
{} +//~^ ERROR E0799 + +fn main() {} diff --git a/tests/ui/error-codes/E0799.stderr b/tests/ui/error-codes/E0799.stderr new file mode 100644 index 0000000000000..3639424e466f0 --- /dev/null +++ b/tests/ui/error-codes/E0799.stderr @@ -0,0 +1,9 @@ +error[E0799]: expected type or const parameter, found function `main` + --> $DIR/E0799.rs:1:31 + | +LL | fn test() -> impl Sized + use
{} + | ^^^^ not a type or const parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0799`. diff --git a/tests/ui/error-codes/E0800.rs b/tests/ui/error-codes/E0800.rs new file mode 100644 index 0000000000000..6112157feca5d --- /dev/null +++ b/tests/ui/error-codes/E0800.rs @@ -0,0 +1,4 @@ +fn test() -> impl Sized + use {} +//~^ ERROR E0800 + +fn main() {} diff --git a/tests/ui/error-codes/E0800.stderr b/tests/ui/error-codes/E0800.stderr new file mode 100644 index 0000000000000..282981a91732e --- /dev/null +++ b/tests/ui/error-codes/E0800.stderr @@ -0,0 +1,9 @@ +error[E0800]: cannot find type or const parameter `Missing` in this scope + --> $DIR/E0800.rs:1:31 + | +LL | fn test() -> impl Sized + use {} + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0800`. diff --git a/tests/ui/impl-trait/precise-capturing/bad-params.stderr b/tests/ui/impl-trait/precise-capturing/bad-params.stderr index 94577881d6c3b..07ada8da30019 100644 --- a/tests/ui/impl-trait/precise-capturing/bad-params.stderr +++ b/tests/ui/impl-trait/precise-capturing/bad-params.stderr @@ -1,4 +1,4 @@ -error[E0412]: cannot find type or const parameter `T` in this scope +error[E0800]: cannot find type or const parameter `T` in this scope --> $DIR/bad-params.rs:1:34 | LL | fn missing() -> impl Sized + use {} @@ -17,19 +17,19 @@ LL | fn missing_self() -> impl Sized + use {} | | | `Self` not allowed in a function -error[E0573]: expected type or const parameter, found function `hello` +error[E0799]: expected type or const parameter, found function `hello` --> $DIR/bad-params.rs:13:32 | LL | fn hello() -> impl Sized + use {} | ^^^^^ not a type or const parameter -error[E0573]: expected type or const parameter, found local variable `x` +error[E0799]: expected type or const parameter, found local variable `x` --> $DIR/bad-params.rs:16:35 | LL | fn arg(x: ()) -> impl Sized + use {} | ^ not a type or const parameter -error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias +error[E0799]: `Self` can't be captured in `use<...>` precise captures list, since it is an alias --> $DIR/bad-params.rs:9:48 | LL | impl MyType { @@ -39,5 +39,5 @@ LL | fn self_is_not_param() -> impl Sized + use {} error: aborting due to 5 previous errors -Some errors have detailed explanations: E0411, E0412, E0573. +Some errors have detailed explanations: E0411, E0799, E0800. For more information about an error, try `rustc --explain E0411`.