Skip to content

Commit

Permalink
Auto merge of #130414 - compiler-errors:precise-capturing-arg-valid, …
Browse files Browse the repository at this point in the history
…r=jieyouxu

Do precise capturing arg validation in resolve

Moves the validation of precise capturing args (`use<T, N>`) out of `resolve_bound_vars` and into `rustc_resolve`. This both simplifies the impl and fixes a bug when we have `use<arg>` where `arg` is one of the function args.

This also introduces new error codes specifically for precise capturing, to avoid reusing the other error codes which are not as accurate.

Fixes #130399
  • Loading branch information
bors committed Sep 16, 2024
2 parents 13b5a4e + ae8b460 commit 3a22be3
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 33 deletions.
19 changes: 19 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0799.md
Original file line number Diff line number Diff line change
@@ -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<main> {}
fn bad2(x: ()) -> impl Sized + use<x> {}
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.
11 changes: 11 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0800.md
Original file line number Diff line number Diff line change
@@ -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<T> {}
```

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.
2 changes: 2 additions & 0 deletions compiler/rustc_error_codes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ E0795: 0795,
E0796: 0796,
E0797: 0797,
E0798: 0798,
E0799: 0799,
E0800: 0800,
);
)
}
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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:?}"),
);
}
},
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/errors/precise_captures.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_errors::E0799;
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};

Expand Down Expand Up @@ -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,
Expand Down
43 changes: 38 additions & 5 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand All @@ -413,6 +415,7 @@ impl<'a> PathSource<'a> {
| PathSource::TupleStruct(..)
| PathSource::Delegation => ValueNS,
PathSource::TraitItem(ns) => ns,
PathSource::PreciseCapturingArg(ns) => ns,
}
}

Expand All @@ -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,
}
}

Expand Down Expand Up @@ -466,6 +472,7 @@ impl<'a> PathSource<'a> {
_ => "value",
},
PathSource::Delegation => "function",
PathSource::PreciseCapturingArg(..) => "type or const parameter",
}
}

Expand Down Expand Up @@ -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,
}
}

Expand All @@ -551,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,
}
}
}
Expand Down Expand Up @@ -1077,9 +1095,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),
);
}
}
}
Expand Down Expand Up @@ -1889,7 +1917,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
Expand Down Expand Up @@ -3982,7 +4013,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 {
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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[..] {
Expand Down
5 changes: 0 additions & 5 deletions tests/crashes/130399.rs

This file was deleted.

4 changes: 4 additions & 0 deletions tests/ui/error-codes/E0799.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn test() -> impl Sized + use<main> {}
//~^ ERROR E0799

fn main() {}
9 changes: 9 additions & 0 deletions tests/ui/error-codes/E0799.stderr
Original file line number Diff line number Diff line change
@@ -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<main> {}
| ^^^^ not a type or const parameter

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0799`.
4 changes: 4 additions & 0 deletions tests/ui/error-codes/E0800.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn test() -> impl Sized + use<Missing> {}
//~^ ERROR E0800

fn main() {}
9 changes: 9 additions & 0 deletions tests/ui/error-codes/E0800.stderr
Original file line number Diff line number Diff line change
@@ -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<Missing> {}
| ^^^^^^^ not found in this scope

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0800`.
9 changes: 6 additions & 3 deletions tests/ui/impl-trait/precise-capturing/bad-params.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
fn missing() -> impl Sized + use<T> {}
//~^ 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<Self> {}
//~^ ERROR cannot find type `Self` in this scope
//~^ ERROR cannot find type or const parameter `Self` in this scope

struct MyType;
impl MyType {
Expand All @@ -11,6 +11,9 @@ impl MyType {
}

fn hello() -> impl Sized + use<hello> {}
//~^ 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<x> {}
//~^ ERROR expected type or const parameter, found local variable `x`

fn main() {}
28 changes: 17 additions & 11 deletions tests/ui/impl-trait/precise-capturing/bad-params.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0412]: cannot find type `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<T> {}
Expand All @@ -9,29 +9,35 @@ help: you might be missing a type parameter
LL | fn missing<T>() -> impl Sized + use<T> {}
| +++

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<Self> {}
| ------------ ^^^^ `Self` is only available in impls, traits, and type definitions
| |
| `Self` not allowed in a function

error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias
error[E0799]: expected type or const parameter, found function `hello`
--> $DIR/bad-params.rs:13:32
|
LL | fn hello() -> impl Sized + use<hello> {}
| ^^^^^ not a type or const parameter

error[E0799]: expected type or const parameter, found local variable `x`
--> $DIR/bad-params.rs:16:35
|
LL | fn arg(x: ()) -> impl Sized + use<x> {}
| ^ not a type or const parameter

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 {
| ----------- `Self` is not a generic argument, but an alias to the type of the implementation
LL | fn self_is_not_param() -> impl Sized + use<Self> {}
| ^^^^

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<hello> {}
| ^^^^^

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, E0799, E0800.
For more information about an error, try `rustc --explain E0411`.

0 comments on commit 3a22be3

Please sign in to comment.