Skip to content

Commit

Permalink
Use a path instead of an ident (and stop manually resolving)
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Apr 5, 2024
1 parent e6dc0de commit e154b64
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 84 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2191,12 +2191,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.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -924,8 +924,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);
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,8 +649,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);
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1787,13 +1787,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),
})
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(">")
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 13 additions & 3 deletions compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,9 +584,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(),
});
}
},
}
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/errors/precise_captures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
66 changes: 12 additions & 54 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1059,64 +1059,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) {
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/impl-trait/precise-capturing/bad-params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
32 changes: 21 additions & 11 deletions tests/ui/impl-trait/precise-capturing/bad-params.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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`.

0 comments on commit e154b64

Please sign in to comment.