Use a path instead of an ident (and stop manually resolving)

This commit is contained in:
Michael Goulet 2024-04-04 20:23:52 -04:00
parent ce8961039e
commit 52c6b101ea
12 changed files with 81 additions and 84 deletions

View file

@ -2188,12 +2188,12 @@ pub enum TraitObjectSyntax {
None,
}
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum PreciseCapturingArg {
/// Lifetime parameter
Lifetime(Lifetime),
/// Type or const parameter
Arg(Ident, NodeId),
Arg(Path, NodeId),
}
/// Inline assembly operand explicit register or register class.

View file

@ -928,8 +928,8 @@ pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturin
PreciseCapturingArg::Lifetime(lt) => {
vis.visit_lifetime(lt);
}
PreciseCapturingArg::Arg(ident, id) => {
vis.visit_ident(ident);
PreciseCapturingArg::Arg(path, id) => {
vis.visit_path(path);
vis.visit_id(id);
}
}

View file

@ -653,8 +653,8 @@ pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
PreciseCapturingArg::Lifetime(lt) => {
visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg);
}
PreciseCapturingArg::Arg(ident, _) => {
visitor.visit_ident(*ident);
PreciseCapturingArg::Arg(path, id) => {
visitor.visit_path(path, *id);
}
}
}

View file

@ -1790,13 +1790,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
PreciseCapturingArg::Lifetime(lt) => {
hir::PreciseCapturingArg::Lifetime(self.lower_lifetime(lt))
}
PreciseCapturingArg::Arg(ident, node_id) => {
let res = self.resolver.get_partial_res(*node_id).map_or(Res::Err, |partial_res| {
PreciseCapturingArg::Arg(path, id) => {
let [segment] = path.segments.as_slice() else {
panic!();
};
let res = self.resolver.get_partial_res(*id).map_or(Res::Err, |partial_res| {
partial_res.full_res().expect("no partial res expected for precise capture arg")
});
hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
hir_id: self.lower_node_id(*node_id),
ident: self.lower_ident(*ident),
hir_id: self.lower_node_id(*id),
ident: self.lower_ident(segment.ident),
res: self.lower_res(res),
})
}

View file

@ -1156,7 +1156,7 @@ impl<'a> State<'a> {
self.word("use");
self.word("<");
self.commasep(Inconsistent, precise_capturing_args, |s, arg| match arg {
ast::PreciseCapturingArg::Arg(a, _) => s.print_ident(*a),
ast::PreciseCapturingArg::Arg(p, _) => s.print_path(p, false, 0),
ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt),
});
self.word(">")

View file

@ -39,6 +39,9 @@ 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_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
hir_analysis_cannot_capture_late_bound_const =
cannot capture late-bound const parameter in {$what}
.label = parameter defined here

View file

@ -583,9 +583,19 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
self.resolve_type_ref(def_id.expect_local(), param.hir_id);
}
Res::Err => {}
_ => {
// This is handled in resolve
self.tcx.dcx().delayed_bug(format!("parameter should have been resolved"));
Res::SelfTyAlias { alias_to, .. } => {
self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
span: param.ident.span,
self_span: self.tcx.def_span(alias_to),
what: self.tcx.def_descr(alias_to),
});
}
res => {
self.tcx.dcx().emit_err(errors::BadPreciseCapture {
span: param.ident.span,
kind: "type or const",
found: res.descr().to_string(),
});
}
},
}

View file

@ -32,6 +32,16 @@ pub struct BadPreciseCapture {
pub found: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_precise_capture_self_alias)]
pub struct PreciseCaptureSelfAlias {
#[primary_span]
pub span: Span,
#[label]
pub self_span: Span,
pub what: &'static str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_duplicate_precise_capture)]
pub struct DuplicatePreciseCapture {

View file

@ -697,11 +697,14 @@ impl<'a> Parser<'a> {
if self_.check_keyword(kw::SelfUpper) {
self_.bump();
Ok(PreciseCapturingArg::Arg(
self_.prev_token.ident().unwrap().0,
ast::Path::from_ident(self_.prev_token.ident().unwrap().0),
DUMMY_NODE_ID,
))
} else if self_.check_ident() {
Ok(PreciseCapturingArg::Arg(self_.parse_ident().unwrap(), DUMMY_NODE_ID))
Ok(PreciseCapturingArg::Arg(
ast::Path::from_ident(self_.parse_ident()?),
DUMMY_NODE_ID,
))
} else if self_.check_lifetime() {
Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
} else {

View file

@ -1056,64 +1056,22 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
match arg {
// Lower the lifetime regularly; we'll resolve the lifetime and check
// it's a parameter later on in HIR lowering.
PreciseCapturingArg::Lifetime(_) => visit::walk_precise_capturing_arg(self, arg),
PreciseCapturingArg::Lifetime(_) => {}
PreciseCapturingArg::Arg(ident, node_id) => {
let ident = ident.normalize_to_macros_2_0();
'found: {
for (rib_t, rib_v) in
std::iter::zip(&self.ribs.type_ns, &self.ribs.value_ns).rev()
{
if let Some(res) = rib_t.bindings.get(&ident).or(rib_v.bindings.get(&ident))
{
self.r.record_partial_res(*node_id, PartialRes::new(*res));
// Validate that this is a parameter
match res {
Res::Def(DefKind::TyParam | DefKind::ConstParam, _)
| Res::SelfTyParam { .. } => {}
Res::SelfTyAlias { .. } => {
self.report_error(
ident.span,
ResolutionError::FailedToResolve {
segment: Some(ident.name),
label: "`Self` cannot be captured because it is not a type parameter".to_string(),
suggestion: None,
module: None,
},
);
}
_ => {
self.report_error(
ident.span,
ResolutionError::FailedToResolve {
segment: Some(ident.name),
label: format!(
"expected type or const parameter, found {}",
res.descr()
),
suggestion: None,
module: None,
},
);
}
}
break 'found;
}
}
self.report_error(
ident.span,
ResolutionError::FailedToResolve {
segment: Some(ident.name),
label: "could not find type or const parameter".to_string(),
suggestion: None,
module: None,
},
);
PreciseCapturingArg::Arg(path, id) => {
let mut check_ns = |ns| {
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
};
// 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));
} else {
self.smart_resolve_path(*id, &None, path, PathSource::Type);
}
}
}
visit::walk_precise_capturing_arg(self, arg)
}
fn visit_generics(&mut self, generics: &'ast Generics) {

View file

@ -2,15 +2,15 @@
//~^ WARN the feature `precise_capturing` is incomplete
fn missing() -> impl use<T> Sized {}
//~^ ERROR could not find type or const parameter
//~^ ERROR cannot find type `T` in this scope
fn missing_self() -> impl use<Self> Sized {}
//~^ ERROR could not find type or const parameter
//~^ ERROR cannot find type `Self` in this scope
struct MyType;
impl MyType {
fn self_is_not_param() -> impl use<Self> Sized {}
//~^ ERROR `Self` cannot be captured because it is not a type parameter
//~^ ERROR `Self` can't be captured in `use<...>` precise captures list, since it is an alias
}
fn main() {}

View file

@ -1,20 +1,21 @@
error[E0433]: failed to resolve: could not find type or const parameter
error[E0412]: cannot find type `T` in this scope
--> $DIR/bad-params.rs:4:26
|
LL | fn missing() -> impl use<T> Sized {}
| ^ could not find type or const parameter
| ^ not found in this scope
|
help: you might be missing a type parameter
|
LL | fn missing<T>() -> impl use<T> Sized {}
| +++
error[E0433]: failed to resolve: could not find type or const parameter
error[E0411]: cannot find type `Self` in this scope
--> $DIR/bad-params.rs:7:31
|
LL | fn missing_self() -> impl use<Self> Sized {}
| ^^^^ could not find type or const parameter
error[E0433]: failed to resolve: `Self` cannot be captured because it is not a type parameter
--> $DIR/bad-params.rs:12:40
|
LL | fn self_is_not_param() -> impl use<Self> Sized {}
| ^^^^ `Self` cannot be captured because it is not a type parameter
| ------------ ^^^^ `Self` is only available in impls, traits, and type definitions
| |
| `Self` not allowed in a function
warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/bad-params.rs:1:12
@ -25,6 +26,15 @@ LL | #![feature(precise_capturing)]
= note: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
= note: `#[warn(incomplete_features)]` on by default
error: `Self` can't be captured in `use<...>` precise captures list, since it is an alias
--> $DIR/bad-params.rs:12:40
|
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 use<Self> Sized {}
| ^^^^
error: aborting due to 3 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0433`.
Some errors have detailed explanations: E0411, E0412.
For more information about an error, try `rustc --explain E0411`.