1
Fork 0

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, None,
} }
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum PreciseCapturingArg { pub enum PreciseCapturingArg {
/// Lifetime parameter /// Lifetime parameter
Lifetime(Lifetime), Lifetime(Lifetime),
/// Type or const parameter /// Type or const parameter
Arg(Ident, NodeId), Arg(Path, NodeId),
} }
/// Inline assembly operand explicit register or register class. /// 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) => { PreciseCapturingArg::Lifetime(lt) => {
vis.visit_lifetime(lt); vis.visit_lifetime(lt);
} }
PreciseCapturingArg::Arg(ident, id) => { PreciseCapturingArg::Arg(path, id) => {
vis.visit_ident(ident); vis.visit_path(path);
vis.visit_id(id); vis.visit_id(id);
} }
} }

View file

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

View file

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

View file

@ -1156,7 +1156,7 @@ impl<'a> State<'a> {
self.word("use"); self.word("use");
self.word("<"); self.word("<");
self.commasep(Inconsistent, precise_capturing_args, |s, arg| match arg { 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), ast::PreciseCapturingArg::Lifetime(lt) => s.print_lifetime(*lt),
}); });
self.word(">") 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_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 = hir_analysis_cannot_capture_late_bound_const =
cannot capture late-bound const parameter in {$what} cannot capture late-bound const parameter in {$what}
.label = parameter defined here .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); self.resolve_type_ref(def_id.expect_local(), param.hir_id);
} }
Res::Err => {} Res::Err => {}
_ => { Res::SelfTyAlias { alias_to, .. } => {
// This is handled in resolve self.tcx.dcx().emit_err(errors::PreciseCaptureSelfAlias {
self.tcx.dcx().delayed_bug(format!("parameter should have been resolved")); 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, 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)] #[derive(Diagnostic)]
#[diag(hir_analysis_duplicate_precise_capture)] #[diag(hir_analysis_duplicate_precise_capture)]
pub struct DuplicatePreciseCapture { pub struct DuplicatePreciseCapture {

View file

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

View file

@ -1056,64 +1056,22 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
match arg { match arg {
// Lower the lifetime regularly; we'll resolve the lifetime and check // Lower the lifetime regularly; we'll resolve the lifetime and check
// it's a parameter later on in HIR lowering. // 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) => { PreciseCapturingArg::Arg(path, id) => {
let ident = ident.normalize_to_macros_2_0(); let mut check_ns = |ns| {
'found: { self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
for (rib_t, rib_v) in };
std::iter::zip(&self.ribs.type_ns, &self.ribs.value_ns).rev() // Like `Ty::Param`, we try resolving this as both a const and a type.
{ if !check_ns(TypeNS) && check_ns(ValueNS) {
if let Some(res) = rib_t.bindings.get(&ident).or(rib_v.bindings.get(&ident)) self.smart_resolve_path(*id, &None, path, PathSource::Expr(None));
{ } else {
self.r.record_partial_res(*node_id, PartialRes::new(*res)); self.smart_resolve_path(*id, &None, path, PathSource::Type);
// 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; visit::walk_precise_capturing_arg(self, arg)
}
}
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,
},
);
}
}
}
} }
fn visit_generics(&mut self, generics: &'ast Generics) { fn visit_generics(&mut self, generics: &'ast Generics) {

View file

@ -2,15 +2,15 @@
//~^ WARN the feature `precise_capturing` is incomplete //~^ WARN the feature `precise_capturing` is incomplete
fn missing() -> impl use<T> Sized {} 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 {} 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; struct MyType;
impl MyType { impl MyType {
fn self_is_not_param() -> impl use<Self> Sized {} 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() {} 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 --> $DIR/bad-params.rs:4:26
| |
LL | fn missing() -> impl use<T> Sized {} 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 --> $DIR/bad-params.rs:7:31
| |
LL | fn missing_self() -> impl use<Self> Sized {} LL | fn missing_self() -> impl use<Self> Sized {}
| ^^^^ could not find type or const parameter | ------------ ^^^^ `Self` is only available in impls, traits, and type definitions
| |
error[E0433]: failed to resolve: `Self` cannot be captured because it is not a type parameter | `Self` not allowed in a function
--> $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
warning: the feature `precise_capturing` is incomplete and may not be safe to use and/or cause compiler crashes 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 --> $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: see issue #123432 <https://github.com/rust-lang/rust/issues/123432> for more information
= note: `#[warn(incomplete_features)]` on by default = 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 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`.