From 26cd5486f89d49b18af91d5c44d6f93e55261ba6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Jun 2023 18:19:51 +0000 Subject: [PATCH] Account for late-bound vars from parent arg-position impl trait --- compiler/rustc_hir_analysis/messages.ftl | 6 +++ .../src/collect/resolve_bound_vars.rs | 45 +++++++++++++++++++ compiler/rustc_hir_analysis/src/errors.rs | 18 ++++++++ .../nested-apit-mentioning-outer-bound-var.rs | 11 +++++ ...ted-apit-mentioning-outer-bound-var.stderr | 17 +++++++ 5 files changed, 97 insertions(+) create mode 100644 tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs create mode 100644 tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index cd6cf36baa4..64743e2abdc 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -99,6 +99,12 @@ hir_analysis_invalid_union_field = hir_analysis_invalid_union_field_sugg = wrap the field type in `ManuallyDrop<...>` +hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl + .label = const parameter declared here + +hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl + .label = type parameter declared here + hir_analysis_lifetimes_or_bounds_mismatch_on_trait = lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration .label = lifetimes do not match {$item_kind} in trait 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 d20f39e9b05..a5e2161732b 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1379,6 +1379,7 @@ fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) { let mut late_depth = 0; let mut scope = self.scope; let mut crossed_anon_const = false; + let result = loop { match *scope { Scope::Body { s, .. } => { @@ -1446,6 +1447,50 @@ fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) { return; } + // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT. + // AST-based resolution does not care for impl-trait desugaring, which are the + // responsibility of lowering. This may create a mismatch between the resolution + // AST found (`param_def_id`) which points to HRTB, and what HIR allows. + // ``` + // fn foo(x: impl for Trait>) {} + // ``` + // + // In such case, walk back the binders to diagnose it properly. + let mut scope = self.scope; + loop { + match *scope { + Scope::Binder { + where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), .. + } => { + let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) { + DefKind::TyParam => errors::LateBoundInApit::Type { + span: self.tcx.hir().span(hir_id), + param_span: self.tcx.def_span(param_def_id), + }, + DefKind::ConstParam => errors::LateBoundInApit::Const { + span: self.tcx.hir().span(hir_id), + param_span: self.tcx.def_span(param_def_id), + }, + kind => { + bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id())) + } + }); + self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); + return; + } + Scope::Root { .. } => break, + Scope::Binder { s, .. } + | Scope::Body { s, .. } + | Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } + | Scope::AnonConstBoundary { s } => { + scope = s; + } + } + } + self.tcx.sess.delay_span_bug( self.tcx.hir().span(hir_id), format!("could not resolve {param_def_id:?}"), diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 7dce1272f96..aa94f4dfa7c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -875,3 +875,21 @@ pub(crate) enum ReturnTypeNotationIllegalParam { param_span: Span, }, } + +#[derive(Diagnostic)] +pub(crate) enum LateBoundInApit { + #[diag(hir_analysis_late_bound_type_in_apit)] + Type { + #[primary_span] + span: Span, + #[label] + param_span: Span, + }, + #[diag(hir_analysis_late_bound_const_in_apit)] + Const { + #[primary_span] + span: Span, + #[label] + param_span: Span, + }, +} diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs new file mode 100644 index 00000000000..e9ae00df7a0 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.rs @@ -0,0 +1,11 @@ +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Trait { + type Assoc; +} + +fn uwu(_: impl for Trait<(), Assoc = impl Trait>) {} +//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr new file mode 100644 index 00000000000..1124076c23c --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/nested-apit-mentioning-outer-bound-var.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/nested-apit-mentioning-outer-bound-var.rs:1:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: `impl Trait` can only mention type parameters from an fn or impl + --> $DIR/nested-apit-mentioning-outer-bound-var.rs:8:52 + | +LL | fn uwu(_: impl for Trait<(), Assoc = impl Trait>) {} + | - type parameter declared here ^ + +error: aborting due to previous error; 1 warning emitted +