summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-02-17 00:19:34 +0100
committerGitHub <noreply@github.com>2023-02-17 00:19:34 +0100
commit089e8c03bcd69e559c6c1d03051ca3b7a81ac688 (patch)
treee8a41d945816db9e92171388ed76a00ba2394734
parent6379c727ace0cfc1eaab093f297b97e1ffb8bb30 (diff)
parent95f35fe443afd8a0437390973fbd206db9fd7fd4 (diff)
downloadrust-089e8c03bcd69e559c6c1d03051ca3b7a81ac688.tar.gz
Rollup merge of #107489 - compiler-errors:non_lifetime_binders, r=cjgillot
Implement partial support for non-lifetime binders This implements support for non-lifetime binders. It's pretty useless currently, but I wanted to put this up so the implementation can be discussed. Specifically, this piggybacks off of the late-bound lifetime collection code in `rustc_hir_typeck::collect::lifetimes`. This seems like a necessary step given the fact we don't resolve late-bound regions until this point, and binders are sometimes merged. Q: I'm not sure if I should go along this route, or try to modify the earlier nameres code to compute the right bound var indices for type and const binders eagerly... If so, I'll need to rename all these queries to something more appropriate (I've done this for `resolve_lifetime::Region` -> `resolve_lifetime::ResolvedArg`) cc rust-lang/types-team#81 r? `@ghost`
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs34
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs55
-rw-r--r--compiler/rustc_attr/src/builtin.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs91
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs (renamed from compiler/rustc_hir_analysis/src/collect/lifetimes.rs)403
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs30
-rw-r--r--compiler/rustc_lint/src/builtin.rs12
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs2
-rw-r--r--compiler/rustc_middle/src/middle/resolve_bound_vars.rs (renamed from compiler/rustc_middle/src/middle/resolve_lifetime.rs)14
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs31
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs4
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/query.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs3
-rw-r--r--compiler/rustc_resolve/src/late.rs10
-rw-r--r--compiler/rustc_session/src/errors.rs22
-rw-r--r--compiler/rustc_session/src/parse.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs9
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs4
-rw-r--r--tests/ui/bounds-lifetime.stderr11
-rw-r--r--tests/ui/closures/binder/disallow-const.stderr6
-rw-r--r--tests/ui/closures/binder/disallow-ty.stderr6
-rw-r--r--tests/ui/conditional-compilation/cfg-generic-params.stderr46
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr12
-rw-r--r--tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr11
-rw-r--r--tests/ui/parser/recover-fn-ptr-with-generics.stderr12
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.rs19
-rw-r--r--tests/ui/traits/non_lifetime_binders/basic.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.rs23
-rw-r--r--tests/ui/traits/non_lifetime_binders/fail.stderr43
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-dyn.stderr17
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.rs13
-rw-r--r--tests/ui/traits/non_lifetime_binders/on-ptr.stderr17
48 files changed, 709 insertions, 343 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1535837fd05..d1ae8c1fdbd 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -294,27 +294,6 @@ impl<'a> AstValidator<'a> {
}
}
- fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
- // Check only lifetime parameters are present and that the lifetime
- // parameters that are present have no bounds.
- let non_lt_param_spans: Vec<_> = params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => {
- if !param.bounds.is_empty() {
- let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
- self.session.emit_err(ForbiddenLifetimeBound { spans });
- }
- None
- }
- _ => Some(param.ident.span),
- })
- .collect();
- if !non_lt_param_spans.is_empty() {
- self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
- }
- }
-
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
self.check_decl_num_args(fn_decl);
self.check_decl_cvaradic_pos(fn_decl);
@@ -745,7 +724,6 @@ impl<'a> AstValidator<'a> {
)
.emit();
});
- self.check_late_bound_lifetime_defs(&bfty.generic_params);
if let Extern::Implicit(_) = bfty.ext {
let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
self.maybe_lint_missing_abi(sig_span, ty.id);
@@ -1318,9 +1296,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
for predicate in &generics.where_clause.predicates {
match predicate {
WherePredicate::BoundPredicate(bound_pred) => {
- // A type binding, eg `for<'c> Foo: Send+Clone+'c`
- self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
-
// This is slightly complicated. Our representation for poly-trait-refs contains a single
// binder and thus we only allow a single level of quantification. However,
// the syntax of Rust permits quantification in two places in where clauses,
@@ -1396,11 +1371,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_param_bound(self, bound)
}
- fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
- self.check_late_bound_lifetime_defs(&t.bound_generic_params);
- visit::walk_poly_trait_ref(self, t);
- }
-
fn visit_variant_data(&mut self, s: &'a VariantData) {
self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
}
@@ -1437,10 +1407,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
.emit();
}
- if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
- self.check_late_bound_lifetime_defs(generic_params);
- }
-
if let FnKind::Fn(
_,
_,
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 89ba6f936d1..3af2ef4e727 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi;
+use crate::errors::ForbiddenLifetimeBound;
+
macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
let (visitor, has_feature, span, name, explain, help) =
@@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
}
ImplTraitVisitor { vis: self }.visit_ty(ty);
}
+
+ fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
+ // Check only lifetime parameters are present and that the lifetime
+ // parameters that are present have no bounds.
+ let non_lt_param_spans: Vec<_> = params
+ .iter()
+ .filter_map(|param| match param.kind {
+ ast::GenericParamKind::Lifetime { .. } => None,
+ _ => Some(param.ident.span),
+ })
+ .collect();
+ // FIXME: gate_feature_post doesn't really handle multispans...
+ if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
+ feature_err(
+ &self.sess.parse_sess,
+ sym::non_lifetime_binders,
+ non_lt_param_spans,
+ rustc_errors::fluent::ast_passes_forbidden_non_lifetime_param,
+ )
+ .emit();
+ }
+ for param in params {
+ if !param.bounds.is_empty() {
+ let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
+ self.sess.emit_err(ForbiddenLifetimeBound { spans });
+ }
+ }
+ }
}
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
@@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
..
}) = attr_info
{
- gate_feature_fn!(self, has_feature, attr.span, *name, descr);
+ gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
}
// Check unstable flavors of the `#[doc]` attribute.
if attr.has_name(sym::doc) {
@@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
ast::TyKind::BareFn(bare_fn_ty) => {
// Function pointers cannot be `const`
self.check_extern(bare_fn_ty.ext, ast::Const::No);
+ self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
@@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_ty(self, ty)
}
+ fn visit_generics(&mut self, g: &'a ast::Generics) {
+ for predicate in &g.where_clause.predicates {
+ match predicate {
+ ast::WherePredicate::BoundPredicate(bound_pred) => {
+ // A type binding, eg `for<'c> Foo: Send+Clone+'c`
+ self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
+ }
+ _ => {}
+ }
+ }
+ visit::walk_generics(self, g);
+ }
+
fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
if let ast::FnRetTy::Ty(output_ty) = ret_ty {
if let ast::TyKind::Never = output_ty.kind {
@@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
visit::walk_pat(self, pattern)
}
+ fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
+ self.check_late_bound_lifetime_defs(&t.bound_generic_params);
+ visit::walk_poly_trait_ref(self, t);
+ }
+
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
if let Some(header) = fn_kind.header() {
// Stability of const fn methods are covered in `visit_assoc_item` below.
self.check_extern(header.ext, header.constness);
}
+ if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
+ self.check_late_bound_lifetime_defs(generic_params);
+ }
+
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
}
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 40531c1c164..3d240108b4a 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -731,7 +731,7 @@ pub fn eval_condition(
sess,
sym::cfg_target_compact,
cfg.span,
- &"compact `cfg(target(..))` is experimental and subject to change"
+ "compact `cfg(target(..))` is experimental and subject to change"
).emit();
}
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 5267f73efc8..7122ccdcd2e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -473,6 +473,8 @@ declare_features! (
(active, no_sanitize, "1.42.0", Some(39699), None),
/// Allows using the `non_exhaustive_omitted_patterns` lint.
(active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
+ /// Allows `for<T>` binders in where-clauses
+ (incomplete, non_lifetime_binders, "CURRENT_RUSTC_VERSION", Some(1), None),
/// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
/// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
/// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index e5c176f19ea..221721f5909 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -14,7 +14,7 @@ use crate::errors::{
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
};
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
use crate::require_c_abi_if_c_variadic;
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -225,10 +225,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let tcx = self.tcx();
let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
- match tcx.named_region(lifetime.hir_id) {
- Some(rl::Region::Static) => tcx.lifetimes.re_static,
+ match tcx.named_bound_var(lifetime.hir_id) {
+ Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static,
- Some(rl::Region::LateBound(debruijn, index, def_id)) => {
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
let name = lifetime_name(def_id.expect_local());
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(index),
@@ -237,7 +237,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.mk_re_late_bound(debruijn, br)
}
- Some(rl::Region::EarlyBound(def_id)) => {
+ Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
let name = tcx.hir().ty_param_name(def_id.expect_local());
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
let generics = tcx.generics_of(item_def_id);
@@ -245,7 +245,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name })
}
- Some(rl::Region::Free(scope, id)) => {
+ Some(rbv::ResolvedArg::Free(scope, id)) => {
let name = lifetime_name(id.expect_local());
tcx.mk_re_free(scope, ty::BrNamed(id, name))
@@ -1607,7 +1607,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.ast_region_to_region(lifetime, None)
} else {
self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
- if tcx.named_region(lifetime.hir_id).is_some() {
+ if tcx.named_bound_var(lifetime.hir_id).is_some() {
self.ast_region_to_region(lifetime, None)
} else {
self.re_infer(None, span).unwrap_or_else(|| {
@@ -2600,6 +2600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path<'_>,
+ hir_id: hir::HirId,
permit_variants: bool,
) -> Ty<'tcx> {
let tcx = self.tcx();
@@ -2663,11 +2664,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
});
- let def_id = def_id.expect_local();
- let item_def_id = tcx.hir().ty_param_owner(def_id);
- let generics = tcx.generics_of(item_def_id);
- let index = generics.param_def_id_to_index[&def_id.to_def_id()];
- tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+ match tcx.named_bound_var(hir_id) {
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+ let name =
+ tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
+ let br = ty::BoundTy {
+ var: ty::BoundVar::from_u32(index),
+ kind: ty::BoundTyKind::Param(def_id, name),
+ };
+ tcx.mk_ty(ty::Bound(debruijn, br))
+ }
+ Some(rbv::ResolvedArg::EarlyBound(_)) => {
+ let def_id = def_id.expect_local();
+ let item_def_id = tcx.hir().ty_param_owner(def_id);
+ let generics = tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&def_id.to_def_id()];
+ tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
+ }
+ arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
+ }
}
Res::SelfTyParam { .. } => {
// `Self` in trait or type alias.
@@ -2870,14 +2885,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
hir::TyKind::BareFn(bf) => {
require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span);
- tcx.mk_fn_ptr(self.ty_of_fn(
+ let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn(
ast_ty.hir_id,
bf.unsafety,
bf.abi,
bf.decl,
None,
Some(ast_ty),
- ))
+ ));
+
+ if let Some(guar) =
+ deny_non_region_late_bound(tcx, bf.generic_params, "function pointer")
+ {
+ tcx.ty_error_with_guaranteed(guar)
+ } else {
+ fn_ptr_ty
+ }
}
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
self.maybe_lint_bare_trait(ast_ty, in_path);
@@ -2885,12 +2908,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar,
};
- self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)
+
+ let object_ty = self.conv_object_ty_poly_trait_ref(
+ ast_ty.span,
+ bounds,
+ lifetime,
+ borrowed,
+ repr,
+ );
+
+ if let Some(guar) = bounds.iter().find_map(|trait_ref| {
+ deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object")
+ }) {
+ tcx.ty_error_with_guaranteed(guar)
+ } else {
+ object_ty
+ }
}
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
- self.res_to_ty(opt_self_ty, path, false)
+ self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false)
}
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
@@ -3346,3 +3384,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
}
+
+fn deny_non_region_late_bound(
+ tcx: TyCtxt<'_>,
+ params: &[hir::GenericParam<'_>],
+ where_: &str,
+) -> Option<ErrorGuaranteed> {
+ params.iter().find_map(|bad_param| {
+ let what = match bad_param.kind {
+ hir::GenericParamKind::Type { .. } => "type",
+ hir::GenericParamKind::Const { .. } => "const",
+ hir::GenericParamKind::Lifetime { .. } => return None,
+ };
+
+ let mut diag = tcx.sess.struct_span_err(
+ bad_param.span,
+ format!("late-bound {what} parameter not allowed on {where_} types"),
+ );
+
+ Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() })
+ })
+}
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 456c5bc99b7..8ebe576a224 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -41,8 +41,8 @@ use std::iter;
mod generics_of;
mod item_bounds;
-mod lifetimes;
mod predicates_of;
+mod resolve_bound_vars;
mod type_of;
///////////////////////////////////////////////////////////////////////////
@@ -53,7 +53,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
}
pub fn provide(providers: &mut Providers) {
- lifetimes::provide(providers);
+ resolve_bound_vars::provide(providers);
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 014ee9fcc20..7bcaeadbcf6 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -1,4 +1,4 @@
-use crate::middle::resolve_lifetime as rl;
+use crate::middle::resolve_bound_vars as rbv;
use hir::{
intravisit::{self, Visitor},
GenericParamKind, HirId, Node,
@@ -394,10 +394,11 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
return;
}
- match self.tcx.named_region(lt.hir_id) {
- Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
- Some(rl::Region::LateBound(debruijn, _, _)) if debruijn < self.outer_index => {}
- Some(rl::Region::LateBound(..) | rl::Region::Free(..)) | None => {
+ match self.tcx.named_bound_var(lt.hir_id) {
+ Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {}
+ Some(rbv::ResolvedArg::LateBound(debruijn, _, _))
+ if debruijn < self.outer_index => {}
+ Some(rbv::ResolvedArg::LateBound(..) | rbv::ResolvedArg::Free(..)) | None => {
self.has_late_bound_regions = Some(lt.ident.span);
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index d8606f759b2..8c388040fbf 100644
--- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -16,7 +16,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::*;
+use rustc_middle::middle::resolve_bound_vars::*;
use rustc_middle::ty::{self, ir::TypeVisitor, DefIdTree, TyCtxt, TypeSuperVisitable};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
@@ -24,59 +24,61 @@ use rustc_span::Span;
use std::fmt;
trait RegionExt {
- fn early(param: &GenericParam<'_>) -> (LocalDefId, Region);
+ fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
- fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, Region);
+ fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
fn id(&self) -> Option<DefId>;
- fn shifted(self, amount: u32) -> Region;
+ fn shifted(self, amount: u32) -> ResolvedArg;
}
-impl RegionExt for Region {
- fn early(param: &GenericParam<'_>) -> (LocalDefId, Region) {
- debug!("Region::early: def_id={:?}", param.def_id);
- (param.def_id, Region::EarlyBound(param.def_id.to_def_id()))
+impl RegionExt for ResolvedArg {
+ fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
+ debug!("ResolvedArg::early: def_id={:?}", param.def_id);
+ (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
}
- fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, Region) {
+ fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
let depth = ty::INNERMOST;
debug!(
- "Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
+ "ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
idx, param, depth, param.def_id,
);
- (param.def_id, Region::LateBound(depth, idx, param.def_id.to_def_id()))
+ (param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
}
fn id(&self) -> Option<DefId> {
match *self {
- Region::Static => None,
+ ResolvedArg::StaticLifetime => None,
- Region::EarlyBound(id) | Region::LateBound(_, _, id) | Region::Free(_, id) => Some(id),
+ ResolvedArg::EarlyBound(id)
+ | ResolvedArg::LateBound(_, _, id)
+ | ResolvedArg::Free(_, id) => Some(id),
}
}
- fn shifted(self, amount: u32) -> Region {
+ fn shifted(self, amount: u32) -> ResolvedArg {
match self {
- Region::LateBound(debruijn, idx, id) => {
- Region::LateBound(debruijn.shifted_in(amount), idx, id)
+ ResolvedArg::LateBound(debruijn, idx, id) => {
+ ResolvedArg::LateBound(debruijn.shifted_in(amount), idx, id)
}
_ => self,
}
}
}
-/// Maps the id of each lifetime reference to the lifetime decl
+/// Maps the id of each bound variable reference to the variable decl
/// that it corresponds to.
///
-/// FIXME. This struct gets converted to a `ResolveLifetimes` for
+/// FIXME. This struct gets converted to a `ResolveBoundVars` for
/// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly.
#[derive(Debug, Default)]
-struct NamedRegionMap {
- // maps from every use of a named (not anonymous) lifetime to a
- // `Region` describing how that region is bound
- defs: HirIdMap<Region>,
+struct NamedVarMap {
+ // maps from every use of a named (not anonymous) bound var to a
+ // `ResolvedArg` describing how that variable is bound
+ defs: HirIdMap<ResolvedArg>,
// Maps relevant hir items to the bound vars on them. These include:
// - function defs
@@ -87,9 +89,9 @@ struct NamedRegionMap {
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
}
-struct LifetimeContext<'a, 'tcx> {
+struct BoundVarContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- map: &'a mut NamedRegionMap,
+ map: &'a mut NamedVarMap,
scope: ScopeRef<'a>,
}
@@ -102,7 +104,7 @@ enum Scope<'a> {
Binder {
/// We use an IndexMap here because we want these lifetimes in order
/// for diagnostics.
- lifetimes: FxIndexMap<LocalDefId, Region>,
+ bound_vars: FxIndexMap<LocalDefId, ResolvedArg>,
scope_type: BinderScopeType,
@@ -141,7 +143,7 @@ enum Scope<'a> {
/// inferred in a function body or potentially error outside one),
/// for the default choice of lifetime in a trait object type.
ObjectLifetimeDefault {
- lifetime: Option<Region>,
+ lifetime: Option<ResolvedArg>,
s: ScopeRef<'a>,
},
@@ -150,7 +152,7 @@ enum Scope<'a> {
/// lifetimes encountered when identifying the trait that an associated type
/// is declared on.
Supertrait {
- lifetimes: Vec<ty::BoundVariableKind>,
+ bound_vars: Vec<ty::BoundVariableKind>,
s: ScopeRef<'a>,
},
@@ -185,9 +187,9 @@ struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.0 {
- Scope::Binder { lifetimes, scope_type, hir_id, where_bound_origin, s: _ } => f
+ Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f
.debug_struct("Binder")
- .field("lifetimes", lifetimes)
+ .field("bound_vars", bound_vars)
.field("scope_type", scope_type)
.field("hir_id", hir_id)
.field("where_bound_origin", where_bound_origin)
@@ -202,9 +204,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
.field("lifetime", lifetime)
.field("s", &"..")
.finish(),
- Scope::Supertrait { lifetimes, s: _ } => f
+ Scope::Supertrait { bound_vars, s: _ } => f
.debug_struct("Supertrait")
- .field("lifetimes", lifetimes)
+ .field("bound_vars", bound_vars)
.field("s", &"..")
.finish(),
Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
@@ -219,27 +221,27 @@ type ScopeRef<'a> = &'a Scope<'a>;
pub(crate) fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
- resolve_lifetimes,
+ resolve_bound_vars,
- named_region_map: |tcx, id| tcx.resolve_lifetimes(id).defs.get(&id),
+ named_variable_map: |tcx, id| tcx.resolve_bound_vars(id).defs.get(&id),
is_late_bound_map,
object_lifetime_default,
- late_bound_vars_map: |tcx, id| tcx.resolve_lifetimes(id).late_bound_vars.get(&id),
+ late_bound_vars_map: |tcx, id| tcx.resolve_bound_vars(id).late_bound_vars.get(&id),
..*providers
};
}
-/// Computes the `ResolveLifetimes` map that contains data for an entire `Item`.
+/// Computes the `ResolveBoundVars` map that contains data for an entire `Item`.
/// You should not read the result of this query directly, but rather use
-/// `named_region_map`, `is_late_bound_map`, etc.
+/// `named_variable_map`, `is_late_bound_map`, etc.
#[instrument(level = "debug", skip(tcx))]
-fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLifetimes {
- let mut named_region_map =
- NamedRegionMap { defs: Default::default(), late_bound_vars: Default::default() };
- let mut visitor = LifetimeContext {
+fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
+ let mut named_variable_map =
+ NamedVarMap { defs: Default::default(), late_bound_vars: Default::default() };
+ let mut visitor = BoundVarContext {
tcx,
- map: &mut named_region_map,
+ map: &mut named_variable_map,
scope: &Scope::Root { opt_parent_item: None },
};
match tcx.hir().owner(local_def_id) {
@@ -260,13 +262,13 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
hir::OwnerNode::Crate(_) => {}
}
- let mut rl = ResolveLifetimes::default();
+ let mut rl = ResolveBoundVars::default();
- for (hir_id, v) in named_region_map.defs {
+ for (hir_id, v) in named_variable_map.defs {
let map = rl.defs.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v);
}
- for (hir_id, v) in named_region_map.late_bound_vars {
+ for (hir_id, v) in named_variable_map.late_bound_vars {
let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v);
}
@@ -276,21 +278,33 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveLife
rl
}
-fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &Region) -> ty::BoundVariableKind {
- match region {
- Region::LateBound(_, _, def_id) => {
+fn late_arg_as_bound_arg<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ arg: &ResolvedArg,
+ param: &GenericParam<'tcx>,
+) -> ty::BoundVariableKind {
+ match arg {
+ ResolvedArg::LateBound(_, _, def_id) => {
let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
- ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
+ }
+ GenericParamKind::Type { .. } => {
+ ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
+ }
+ GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
+ }
}
- _ => bug!("{:?} is not a late region", region),
+ _ => bug!("{:?} is not a late argument", arg),
}
}
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
/// Returns the binders in scope and the type of `Binder` that should be created for a poly trait ref.
fn poly_trait_ref_binder_info(&mut self) -> (Vec<ty::BoundVariableKind>, BinderScopeType) {
let mut scope = self.scope;
- let mut supertrait_lifetimes = vec![];
+ let mut supertrait_bound_vars = vec![];
loop {
match scope {
Scope::Body { .. } | Scope::Root { .. } => {
@@ -301,14 +315,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
scope = s;
}
- Scope::Supertrait { s, lifetimes } => {
- supertrait_lifetimes = lifetimes.clone();
+ Scope::Supertrait { s, bound_vars } => {
+ supertrait_bound_vars = bound_vars.clone();
scope = s;
}
Scope::TraitRefBoundary { .. } => {
// We should only see super trait lifetimes if there is a `Binder` above
- assert!(supertrait_lifetimes.is_empty());
+ assert!(supertrait_bound_vars.is_empty());
break (vec![], BinderScopeType::Normal);
}
@@ -316,14 +330,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// Nested poly trait refs have the binders concatenated
let mut full_binders =
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
- full_binders.extend(supertrait_lifetimes.into_iter());
+ full_binders.extend(supertrait_bound_vars.into_iter());
break (full_binders, BinderScopeType::Concatenating);
}
}
}
}
}
-impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
@@ -386,14 +400,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
+ let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
.iter()
- .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair = Region::late(late_bound_idx as u32, param);
- let r = late_region_as_bound_region(self.tcx, &pair.1);
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r)
})
.unzip();
@@ -401,7 +414,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.record_late_bound_vars(e.hir_id, binders);
let scope = Scope::Binder {
hir_id: e.hir_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -461,7 +474,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// conservatively add all resolved lifetimes. Otherwise we run into problems in
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
let parent_item = self.tcx.hir().get_parent_item(item.hir_id());
- let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(parent_item);
+ let resolved_lifetimes: &ResolveBoundVars =
+ self.tcx.resolve_bound_vars(parent_item);
// We need to add *all* deps, since opaque tys may want them from *us*
for (&owner, defs) in resolved_lifetimes.defs.iter() {
defs.iter().for_each(|(&local_id, region)| {
@@ -478,35 +492,33 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
+ origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
generics,
..
}) => {
// We want to start our early-bound indices at the end of the parent scope,
// not including any parent `impl Trait`s.
- let mut lifetimes = FxIndexMap::default();
+ let mut bound_vars = FxIndexMap::default();
debug!(?generics.params);
for param in generics.params {
- match param.kind {
- GenericParamKind::Lifetime { .. } => {
- let (def_id, reg) = Region::early(&param);
- lifetimes.insert(def_id, reg);
- }
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
- }
+ let (def_id, reg) = ResolvedArg::early(&param);
+ bound_vars.insert(def_id, reg);
}
- let scope = Scope::Binder {
- hir_id: item.hir_id(),
- lifetimes,
- s: self.scope,
- scope_type: BinderScopeType::Normal,
- where_bound_origin: None,
- };
+ let scope = Scope::Root { opt_parent_item: Some(parent) };
self.with(scope, |this| {
- let scope = Scope::TraitRefBoundary { s: this.scope };
- this.with(scope, |this| intravisit::walk_item(this, item))
- });
+ let scope = Scope::Binder {
+ hir_id: item.hir_id(),
+ bound_vars,
+ s: this.scope,
+ scope_type: BinderScopeType::Normal,
+ where_bound_origin: None,
+ };
+ this.with(scope, |this| {
+ let scope = Scope::TraitRefBoundary { s: this.scope };
+ this.with(scope, |this| intravisit::walk_item(this, item))
+ });
+ })
}
hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Enum(_, generics)
@@ -516,18 +528,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(generics, ..)
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
- let lifetimes = generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
- })
- .collect();
+ let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: item.hir_id(),
- lifetimes,
+ bound_vars,
scope_type: BinderScopeType::Normal,
s: self.scope,
where_bound_origin: None,
@@ -562,21 +567,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
match ty.kind {
hir::TyKind::BareFn(c) => {
- let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) = c
+ let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
.generic_params
.iter()
- .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair = Region::late(late_bound_idx as u32, param);
- let r = late_region_as_bound_region(self.tcx, &pair.1);
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r)
})
.unzip();
self.record_late_bound_vars(ty.hir_id, binders);
let scope = Scope::Binder {
hir_id: ty.hir_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -674,7 +678,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
- let Some(Region::LateBound(_, _, def_id)) = def else {
+ let Some(ResolvedArg::LateBound(_, _, def_id)) = def else {
continue
};
let Some(def_id) = def_id.as_local() else {
@@ -722,18 +726,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
Type(bounds, ty) => {
let generics = &trait_item.generics;
- let lifetimes = generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
- })
- .collect();
+ let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(trait_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: trait_item.hir_id(),
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -768,18 +765,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}),
Type(ty) => {
let generics = &impl_item.generics;
- let lifetimes: FxIndexMap<LocalDefId, Region> = generics
- .params
- .iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => Some(Region::early(param)),
- GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
- })
- .collect();
+ let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
+ generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(impl_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: impl_item.hir_id(),
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -803,7 +794,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
match lifetime_ref.res {
- hir::LifetimeName::Static => self.insert_lifetime(lifetime_ref, Region::Static),
+ hir::LifetimeName::Static => {
+ self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime)
+ }
hir::LifetimeName::Param(param_def_id) => {
self.resolve_lifetime_ref(param_def_id, lifetime_ref)
}
@@ -814,13 +807,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
- fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
+ fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
if let Some(args) = segment.args {
self.visit_segment_args(path.res, depth, args);
}
}
+ if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
+ self.resolve_type_ref(param_def_id.expect_local(), hir_id);
+ }
}
fn visit_fn(
@@ -869,24 +865,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
origin,
..
}) => {
- let lifetimes: FxIndexMap<LocalDefId, Region> =
+
+ let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
- .iter()
- .filter(|param| {
- matches!(param.kind, GenericParamKind::Lifetime { .. })
- })
- .enumerate()
- .map(|(late_bound_idx, param)| {
- Region::late(late_bound_idx as u32, param)
- })
- .collect();
- let binders: Vec<_> =
- lifetimes
- .iter()
- .map(|(_, region)| {
- late_region_as_bound_region(this.tcx, region)
- })
- .collect();
+ .iter()
+ .enumerate()
+ .map(|(late_bound_idx, param)| {
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
+ (pair, r)
+ })
+ .unzip();
this.record_late_bound_vars(hir_id, binders.clone());
// Even if there are no lifetimes defined here, we still wrap it in a binder
// scope. If there happens to be a nested poly trait ref (an error), that
@@ -894,7 +883,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// being wrong.
let scope = Scope::Binder {
hir_id,
- lifetimes,
+ bound_vars,
s: this.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: Some(origin),
@@ -920,7 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if lt.res != hir::LifetimeName::Static {
continue;
}
- this.insert_lifetime(lt, Region::Static);
+ this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
this.tcx
.sess
.struct_span_warn(
@@ -964,7 +953,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
self.record_late_bound_vars(*hir_id, binders);
let scope = Scope::Binder {
hir_id: *hir_id,
- lifetimes: FxIndexMap::default(),
+ bound_vars: FxIndexMap::default(),
s: self.scope,
scope_type,
where_bound_origin: None,
@@ -983,16 +972,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
let (mut binders, scope_type) = self.poly_trait_ref_binder_info();
let initial_bound_vars = binders.len() as u32;
- let mut lifetimes: FxIndexMap<LocalDefId, Region> = FxIndexMap::default();
- let binders_iter = trait_ref
- .bound_generic_params
- .iter()
- .filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
- .enumerate()
- .map(|(late_bound_idx, param)| {
- let pair = Region::late(initial_bound_vars + late_bound_idx as u32, param);
- let r = late_region_as_bound_region(self.tcx, &pair.1);
- lifetimes.insert(pair.0, pair.1);
+ let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
+ let binders_iter =
+ trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
+ let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
+ let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
+ bound_vars.insert(pair.0, pair.1);
r
});
binders.extend(binders_iter);
@@ -1006,7 +991,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// refs.
let scope = Scope::Binder {
hir_id: trait_ref.trait_ref.hir_ref_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type,
where_bound_origin: None,
@@ -1063,13 +1048,13 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifeti
}
}
-impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
+impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
where
- F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
+ F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
{
- let LifetimeContext { tcx, map, .. } = self;
- let mut this = LifetimeContext { tcx: *tcx, map, scope: &wrap_scope };
+ let BoundVarContext { tcx, map, .. } = self;
+ let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope };
let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
{
let _enter = span.enter();
@@ -1110,23 +1095,25 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
generics: &'tcx hir::Generics<'tcx>,
walk: F,
) where
- F: for<'b, 'c> FnOnce(&'b mut LifetimeContext<'c, 'tcx>),
+ F: for<'b, 'c> FnOnce(&'b mut BoundVarContext<'c, 'tcx>),
{
let mut named_late_bound_vars = 0;
- let lifetimes: FxIndexMap<LocalDefId, Region> = generics
+ let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
.params
.iter()
- .filter_map(|param| match param.kind {
+ .map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
if self.tcx.is_late_bound(param.hir_id) {
let late_bound_idx = named_late_bound_vars;
named_late_bound_vars += 1;
- Some(Region::late(late_bound_idx, param))
+ ResolvedArg::late(late_bound_idx, param)
} else {
- Some(Region::early(param))
+ ResolvedArg::early(param)
}
}
- GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
+ GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
+ ResolvedArg::early(param)
+ }
})
.collect();
@@ -1139,14 +1126,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
})
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair = Region::late(late_bound_idx as u32, param);
- late_region_as_bound_region(self.tcx, &pair.1)
+ let pair = ResolvedArg::late(late_bound_idx as u32, param);
+ late_arg_as_bound_arg(self.tcx, &pair.1, param)
})
.collect();
self.record_late_bound_vars(hir_id, binders);
let scope = Scope::Binder {
hir_id,
- lifetimes,
+ bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
@@ -1177,15 +1164,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Root { opt_parent_item } => {
if let Some(parent_item) = opt_parent_item
&& let parent_generics = self.tcx.generics_of(parent_item)
- && parent_generics.param_def_id_to_index.contains_key(&region_def_id.to_def_id())
+ && parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some()
{
- break Some(Region::EarlyBound(region_def_id.to_def_id()));
+ break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
}
break None;
}
- Scope::Binder { ref lifetimes, scope_type, s, where_bound_origin, .. } => {
- if let Some(&def) = lifetimes.get(&region_def_id) {
+ Scope::Binder { ref bound_vars, scope_type, s, where_bound_origin, .. } => {
+ if let Some(&def) = bound_vars.get(&region_def_id) {
break Some(def.shifted(late_depth));
}
match scope_type {
@@ -1259,7 +1246,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
};
if let Some(mut def) = result {
- if let Region::EarlyBound(..) = def {
+ if let ResolvedArg::EarlyBound(..) = def {
// Do not free early-bound regions, only late-bound ones.
} else if let Some(body_id) = outermost_body {
let fn_id = self.tcx.hir().body_owner(body_id);
@@ -1275,10 +1262,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(..),
..
}) => {
- def = Region::Free(owner_id.to_def_id(), def.id().unwrap());
+ def = ResolvedArg::Free(owner_id.to_def_id(), def.id().unwrap());
}
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(closure), .. }) => {
- def = Region::Free(closure.def_id.to_def_id(), def.id().unwrap());
+ def = ResolvedArg::Free(closure.def_id.to_def_id(), def.id().unwrap());
}
_ => {}
}
@@ -1329,6 +1316,57 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
);
}
+ fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
+ // Walk up the scope chain, tracking the number of fn scopes
+ // that we pass through, until we find a lifetime with the
+ // given name or we run out of scopes.
+ // search.
+ let mut late_depth = 0;
+ let mut scope = self.scope;
+ let result = loop {
+ match *scope {
+ Scope::Body { s, .. } => {
+ scope = s;
+ }
+
+ Scope::Root { opt_parent_item } => {
+ if let Some(parent_item) = opt_parent_item
+ && let parent_generics = self.tcx.generics_of(parent_item)
+ && parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some()
+ {
+ break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
+ }
+ break None;
+ }
+
+ Scope::Binder { ref bound_vars, scope_type, s, .. } => {
+ if let Some(&def) = bound_vars.get(&param_def_id) {
+ break Some(def.shifted(late_depth));
+ }
+ match scope_type {
+ BinderScopeType::Normal => late_depth += 1,
+ BinderScopeType::Concatenating => {}
+ }
+ scope = s;
+ }
+
+ Scope::Elision { s, .. }
+ | Scope::ObjectLifetimeDefault { s, .. }
+ | Scope::Supertrait { s, .. }
+ | Scope::TraitRefBoundary { s, .. } => {
+ scope = s;
+ }
+ }
+ };
+
+ if let Some(def) = result {
+ self.map.defs.insert(hir_id, def);
+ return;
+ }
+
+ span_bug!(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}",);
+ }
+
#[instrument(level = "debug", skip(self))]
fn visit_segment_args(
&mut self,
@@ -1415,10 +1453,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if in_body {
None
} else {
- Some(Region::Static)
+ Some(ResolvedArg::StaticLifetime)
}
}
- ObjectLifetimeDefault::Static => Some(Region::Static),
+ ObjectLifetimeDefault::Static => Some(ResolvedArg::StaticLifetime),
ObjectLifetimeDefault::Param(param_def_id) => {
// This index can be used with `generic_args` since `parent_count == 0`.
let index = generics.param_def_id_to_index[&param_def_id] as usize;
@@ -1507,18 +1545,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// in the trait ref `YY<...>` in `Item: YY<...>`.
for binding in generic_args.bindings {
let scope = Scope::ObjectLifetimeDefault {
- lifetime: if has_lifetime_parameter { None } else { Some(Region::Static) },
+ lifetime: if has_lifetime_parameter {
+ None
+ } else {
+ Some(ResolvedArg::StaticLifetime)
+ },
s: self.scope,
};
if let Some(type_def_id) = type_def_id {
- let lifetimes = LifetimeContext::supertrait_hrtb_lifetimes(
- self.tcx,
- type_def_id,
- binding.ident,
- );
+ let bound_vars =
+ BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
self.with(scope, |this| {
let scope = Scope::Supertrait {
- lifetimes: lifetimes.unwrap_or_default(),
+ bound_vars: bound_vars.unwrap_or_default(),
s: this.scope,
};
this.with(scope, |this| this.visit_assoc_type_binding(binding));
@@ -1541,7 +1580,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
/// ```
/// In this case, if we wanted to the supertrait HRTB lifetimes for `As` on
/// the starting trait `Bar`, we would return `Some(['b, 'a])`.
- fn supertrait_hrtb_lifetimes(
+ fn supertrait_hrtb_vars(
tcx: TyCtxt<'tcx>,
def_id: DefId,
assoc_name: Ident,
@@ -1626,7 +1665,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
scope = s;
}
- Scope::Root { .. } | Scope::Elision { .. } => break Region::Static,
+ Scope::Root { .. } | Scope::Elision { .. } => break ResolvedArg::StaticLifetime,
Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
@@ -1641,7 +1680,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
- fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
+ fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: ResolvedArg) {
debug!(span = ?lifetime_ref.ident.span);
self.map.defs.insert(lifetime_ref.hir_id, def);
}
@@ -1649,7 +1688,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
/// Sometimes we resolve a lifetime, but later find that it is an
/// error (esp. around impl trait). In that case, we remove the
/// entry into `map.defs` so as not to confuse later code.
- fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_def: Region) {
+ fn uninsert_lifetime_on_error(
+ &mut self,
+ lifetime_ref: &'tcx hir::Lifetime,
+ bad_def: ResolvedArg,
+ ) {
let old_value = self.map.defs.remove(&lifetime_ref.hir_id);
assert_eq!(old_value, Some(bad_def));
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 63b170a3c63..69a7235802b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1740,7 +1740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
- let ty = self.astconv().res_to_ty(self_ty, path, true);
+ let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
(path.res, self.handle_raw_ty(path_span, ty))
}
QPath::TypeRelative(ref qself, ref segment) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index 39f4d502259..4fe6c6618f6 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::{self, Region, TyCtxt};
/// This function calls the `visit_ty` method for the parameters
@@ -99,11 +99,11 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
hir::TyKind::Ref(ref lifetime, _) => {
// the lifetime of the Ref
let hir_id = lifetime.hir_id;
- match (self.tcx.named_region(hir_id), self.bound_region) {
+ match (self.tcx.named_bound_var(hir_id), self.bound_region) {
// Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
- (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+ (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
self.found_type = Some(arg);
@@ -115,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(
- Some(rl::Region::LateBound(debruijn_index, _, id)),
+ Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
ty::BrNamed(def_id, _),
) => {
debug!(
@@ -131,10 +131,10 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
(
Some(
- rl::Region::Static
- | rl::Region::Free(_, _)
- | rl::Region::EarlyBound(_)
- | rl::Region::LateBound(_, _, _),
+ rbv::ResolvedArg::StaticLifetime
+ | rbv::ResolvedArg::Free(_, _)
+ | rbv::ResolvedArg::EarlyBound(_)
+ | rbv::ResolvedArg::LateBound(_, _, _),
)
| None,
_,
@@ -186,9 +186,9 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
}
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
- match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
+ match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
// the lifetime of the TyPath!
- (Some(rl::Region::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+ (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
if id == def_id {
self.found_it = true;
@@ -196,7 +196,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
}
}
- (Some(rl::Region::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
+ (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id);
debug!("def_id={:?}", def_id);
@@ -208,10 +208,10 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
(
Some(
- rl::Region::Static
- | rl::Region::EarlyBound(_)
- | rl::Region::LateBound(_, _, _)
- | rl::Region::Free(_, _),
+ rbv::ResolvedArg::StaticLifetime
+ | rbv::ResolvedArg::EarlyBound(_)
+ | rbv::ResolvedArg::LateBound(_, _, _)
+ | rbv::ResolvedArg::Free(_, _),
)
| None,
_,
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 34cf17d25a9..cd793d36de6 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2007,7 +2007,7 @@ impl ExplicitOutlivesRequirements {
inferred_outlives: &[ty::Region<'tcx>],
predicate_span: Span,
) -> Vec<(usize, Span)> {
- use rustc_middle::middle::resolve_lifetime::Region;
+ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
bounds
.iter()
@@ -2017,8 +2017,8 @@ impl ExplicitOutlivesRequirements {
return None;
};
- let is_inferred = match tcx.named_region(lifetime.hir_id) {
- Some(Region::EarlyBound(def_id)) => inferred_outlives
+ let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
+ Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
.iter()
.any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
_ => false,
@@ -2097,7 +2097,7 @@ impl ExplicitOutlivesRequirements {
impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
- use rustc_middle::middle::resolve_lifetime::Region;
+ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
let def_id = item.owner_id.def_id;
if let hir::ItemKind::Struct(_, hir_generics)
@@ -2120,8 +2120,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
let (relevant_lifetimes, bounds, predicate_span, in_where_clause) =
match where_predicate {
hir::WherePredicate::RegionPredicate(predicate) => {
- if let Some(Region::EarlyBound(region_def_id)) =
- cx.tcx.named_region(predicate.lifetime.hir_id)
+ if let Some(ResolvedArg::EarlyBound(region_def_id)) =
+ cx.tcx.named_bound_var(predicate.lifetime.hir_id)
{
(
Self::lifetimes_outliving_lifetime(
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 9227609cc8b..a9fb8b246c6 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -18,7 +18,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 8dc68b1f5a8..0b6774f1b1f 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -29,7 +29,7 @@ pub mod lib_features {
pub mod limits;
pub mod privacy;
pub mod region;
-pub mod resolve_lifetime;
+pub mod resolve_bound_vars;
pub mod stability;
pub fn provide(providers: &mut crate::ty::query::Providers) {
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index c3bf1c717d9..b96d07e7dc8 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -1,4 +1,4 @@
-//! Name resolution for lifetimes: type declarations.
+//! Name resolution for lifetimes and late-bound type and const variables: type declarations.
use crate::ty;
@@ -8,10 +8,10 @@ use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::HashStable;
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
-pub enum Region {
- Static,
- EarlyBound(/* lifetime decl */ DefId),
- LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* lifetime decl */ DefId),
+pub enum ResolvedArg {
+ StaticLifetime,
+ EarlyBound(/* decl */ DefId),
+ LateBound(ty::DebruijnIndex, /* late-bound index */ u32, /* decl */ DefId),
Free(DefId, /* lifetime decl */ DefId),
}
@@ -46,10 +46,10 @@ pub enum ObjectLifetimeDefault {
/// Maps the id of each lifetime reference to the lifetime decl
/// that it corresponds to.
#[derive(Default, HashStable, Debug)]
-pub struct ResolveLifetimes {
+pub struct ResolveBoundVars {
/// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound
- pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>,
+ pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, ResolvedArg>>,
pub late_bound_vars: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4b34f6b4881..c793676146d 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1641,12 +1641,12 @@ rustc_queries! {
/// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params.
/// See `rustc_resolve::late::lifetimes for details.
- query resolve_lifetimes(_: hir::OwnerId) -> &'tcx ResolveLifetimes {
+ query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
arena_cache
desc { "resolving lifetimes" }
}
- query named_region_map(_: hir::OwnerId) ->
- Option<&'tcx FxHashMap<ItemLocalId, Region>> {
+ query named_variable_map(_: hir::OwnerId) ->
+ Option<&'tcx FxHashMap<ItemLocalId, ResolvedArg>> {
desc { "looking up a named region" }
}
query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet<ItemLocalId>> {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 927f18f59b9..c7268d561e5 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,9 @@
+use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::LitToConstInput;
use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::HashStable;
use std::fmt;
@@ -125,16 +127,27 @@ impl<'tcx> Const<'tcx> {
}
}
- use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
match expr.kind {
- ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
- // Find the name and index of the const parameter by indexing the generics of
- // the parent item and construct a `ParamConst`.
- let item_def_id = tcx.parent(def_id);
- let generics = tcx.generics_of(item_def_id);
- let index = generics.param_def_id_to_index[&def_id];
- let name = tcx.item_name(def_id);
- Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ hir::ExprKind::Path(hir::QPath::Resolved(
+ _,
+ &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
+ )) => {
+ match tcx.named_bound_var(expr.hir_id) {
+ Some(rbv::ResolvedArg::EarlyBound(_)) => {
+ // Find the name and index of the const parameter by indexing the generics of
+ // the parent item and construct a `ParamConst`.
+ let item_def_id = tcx.parent(def_id);
+ let generics = tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&def_id];
+ let name = tcx.item_name(def_id);
+ Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+ }
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
+ ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
+ ty,
+ )),
+ arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
+ }
}
_ => None,
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 3687c836fb4..f5322006bec 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -9,7 +9,7 @@ use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::resolve_lifetime;
+use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
use crate::mir::{
@@ -2368,9 +2368,9 @@ impl<'tcx> TyCtxt<'tcx> {
Some(&*candidates)
}
- pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
+ pub fn named_bound_var(self, id: HirId) -> Option<resolve_bound_vars::ResolvedArg> {
debug!(?id, "named_region");
- self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
+ self.named_variable_map(id.owner).and_then(|map| map.get(&id.local_id).cloned())
}
pub fn is_late_bound(self, id: HirId) -> bool {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 9afa37e9ef3..106ce9990e1 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -290,7 +290,7 @@ impl DeepRejectCtxt {
// Impls cannot contain these types as these cannot be named directly.
ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false,
- ty::Placeholder(..) => false,
+ ty::Placeholder(..) | ty::Bound(..) => false,
// Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables.
@@ -310,7 +310,7 @@ impl DeepRejectCtxt {
ty::Error(_) => true,
- ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Bound(..) => {
+ ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {
bug!("unexpected obligation type: {:?}", obligation_ty)
}
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 303675d3ca5..8849e7eab33 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -57,7 +57,7 @@ trivially_parameterized_over_tcx! {
crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::exported_symbols::SymbolExportInfo,
- crate::middle::resolve_lifetime::ObjectLifetimeDefault,
+ crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
ty::DeducedParamAttrs,
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index ed54aa96f5b..f1128d7c8bb 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -6,7 +6,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use crate::middle::lib_features::LibFeatures;
use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
use crate::mir::interpret::GlobalId;
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index 65c15d9c674..c1e7f62dea5 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -2,7 +2,7 @@ use either::Either;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt};
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 225095948af..7cff8996d24 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -18,7 +18,7 @@ use rustc_hir::{
};
use rustc_hir::{MethodKind, Target, Unsafety};
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{ParamEnv, TyCtxt};
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 4675bd79c46..0a0c94e1dfb 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -270,10 +270,11 @@ where
| ty::Ref(..)
| ty::FnPtr(..)
| ty::Param(..)
+ | ty::Bound(..)
| ty::Error(_)
| ty::GeneratorWitness(..)
| ty::GeneratorWitnessMIR(..) => {}
- ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => {
+ ty::Placeholder(..) | ty::Infer(..) => {
bug!("unexpected type: {:?}", ty)
}
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d3bcbbabf55..324de7461cd 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -21,7 +21,7 @@ use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
-use rustc_middle::middle::resolve_lifetime::Set1;
+use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::DefIdTree;
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks};
@@ -2505,7 +2505,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let res = match kind {
ItemRibKind(..) | AssocItemRibKind => Res::Def(def_kind, def_id.to_def_id()),
- NormalRibKind => Res::Err,
+ NormalRibKind => {
+ if self.r.session.features_untracked().non_lifetime_binders {
+ Res::Def(def_kind, def_id.to_def_id())
+ } else {
+ Res::Err
+ }
+ }
_ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
};
self.r.record_partial_res(param.id, PartialRes::new(res));
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 093698f3b35..bd32adbbdbb 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -4,7 +4,7 @@ use crate::cgu_reuse_tracker::CguReuse;
use crate::parse::ParseSess;
use rustc_ast::token;
use rustc_ast::util::literal::LitError;
-use rustc_errors::MultiSpan;
+use rustc_errors::{error_code, DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, MultiSpan};
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
@@ -27,12 +27,22 @@ pub struct CguNotRecorded<'a> {
pub cgu_name: &'a str,
}
-#[derive(Diagnostic)]
-#[diag(session_feature_gate_error, code = "E0658")]
-pub struct FeatureGateError<'a> {
- #[primary_span]
+pub struct FeatureGateError {
pub span: MultiSpan,
- pub explain: &'a str,
+ pub explain: DiagnosticMessage,
+}
+
+impl<'a, T: EmissionGuarantee> IntoDiagnostic<'a, T> for FeatureGateError {
+ #[track_caller]
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, T> {
+ let mut diag = handler.struct_diagnostic(self.explain);
+ diag.set_span(self.span);
+ diag.code(error_code!(E0658));
+ diag
+ }
}
#[derive(Subdiagnostic)]
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 2aa8ca9e4a9..cbdcc5581e5 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -88,7 +88,7 @@ pub fn feature_err<'a>(
sess: &'a ParseSess,
feature: Symbol,
span: impl Into<MultiSpan>,
- explain: &str,
+ explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
feature_err_issue(sess, feature, span, GateIssue::Language, explain)
}
@@ -103,7 +103,7 @@ pub fn feature_err_issue<'a>(
feature: Symbol,
span: impl Into<MultiSpan>,
issue: GateIssue,
- explain: &str,
+ explain: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let span = span.into();
@@ -114,7 +114,7 @@ pub fn feature_err_issue<'a>(
.map(|err| err.cancel());
}
- let mut err = sess.create_err(FeatureGateError { span, explain });
+ let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
err
}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 56835a2466a..37d2aea42ad 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1016,6 +1016,7 @@ symbols! {
non_ascii_idents,
non_exhaustive,
non_exhaustive_omitted_patterns_lint,
+ non_lifetime_binders,
non_modrs_mods,
nontemporal_store,
noop_method_borrow,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 52ed64868c0..91d96655b64 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -60,7 +60,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> Option<(DefId, SubstsRef<'tcx>)> {
let tcx = self.tcx;
let param_env = obligation.param_env;
- let trait_ref = tcx.erase_late_bound_regions(trait_ref);
+ let trait_ref = self.instantiate_binder_with_placeholders(trait_ref);
let trait_self_ty = trait_ref.self_ty();
let mut self_match_impls = vec![];
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 8041066d5d5..45a4cf2a083 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1056,7 +1056,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
- let ty = self.tcx.erase_late_bound_regions(self_ty);
+ let ty = self.instantiate_binder_with_placeholders(self_ty);
let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { return false };
let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false };
let ty::Param(param) = inner_ty.kind() else { return false };
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e9f7c3bc4cc..dae602908a3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -396,7 +396,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// still be provided by a manual implementation for
// this trait and type.
}
- ty::Param(..) | ty::Alias(ty::Projection, ..) => {
+ ty::Param(..)
+ | ty::Alias(ty::Projection, ..)
+ | ty::Placeholder(..)
+ | ty::Bound(..) => {
// In these cases, we don't know what the actual
// type is. Therefore, we cannot break it down
// into its constituent types. So we don't
@@ -448,6 +451,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
self.infcx.probe(|_snapshot| {
+ if obligation.has_non_region_late_bound() {
+ return;
+ }
+
// The code below doesn't care about regions, and the
// self-ty here doesn't escape this probe, so just erase
// any LBR.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 54c8f156f9d..10af968e34f 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -21,7 +21,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
use rustc_hir::PredicateOrigin;
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc_middle::middle::resolve_lifetime as rl;
+use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::fold::ir::TypeFolder;
use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::TypeVisitable;
@@ -200,11 +200,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
}
fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
- let def = cx.tcx.named_region(lifetime.hir_id);
+ let def = cx.tcx.named_bound_var(lifetime.hir_id);
if let Some(
- rl::Region::EarlyBound(node_id)
- | rl::Region::LateBound(_, _, node_id)
- | rl::Region::Free(_, node_id),
+ rbv::ResolvedArg::EarlyBound(node_id)
+ | rbv::ResolvedArg::LateBound(_, _, node_id)
+ | rbv::ResolvedArg::Free(_, node_id),
) = def
{
if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index d88409c356e..fc550936165 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -505,13 +505,13 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio
if let FnRetTy::Return(ty) = sig.decl.output
&& let Some((out, Mutability::Mut, _)) = get_ref_lm(ty)
{
- let out_region = cx.tcx.named_region(out.hir_id);
+ let out_region = cx.tcx.named_bound_var(out.hir_id);
let args: Option<Vec<_>> = sig
.decl
.inputs
.iter()
.filter_map(get_ref_lm)
- .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region)
+ .filter(|&(lt, _, _)| cx.tcx.named_bound_var(lt.hir_id) == out_region)
.map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span))
.collect();
if let Some(args) = args
diff --git a/tests/ui/bounds-lifetime.stderr b/tests/ui/bounds-lifetime.stderr
index a0395ed4904..a3427e21cde 100644
--- a/tests/ui/bounds-lifetime.stderr
+++ b/tests/ui/bounds-lifetime.stderr
@@ -16,17 +16,24 @@ error: lifetime bounds cannot be used in this context
LL | type C = for<'b, 'a: 'b +> fn();
| ^^
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/bounds-lifetime.rs:4:18
|
LL | type D = for<'a, T> fn();
| ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/bounds-lifetime.rs:5:18
|
LL | type E = dyn for<T> Fn();
| ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to 5 previous errors
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/disallow-const.stderr b/tests/ui/closures/binder/disallow-const.stderr
index 3c3b43d8cf3..9f4deaa774d 100644
--- a/tests/ui/closures/binder/disallow-const.stderr
+++ b/tests/ui/closures/binder/disallow-const.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/disallow-const.rs:4:15
|
LL | for<const N: i32> || -> () {};
| ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/closures/binder/disallow-ty.stderr b/tests/ui/closures/binder/disallow-ty.stderr
index 51b6773edea..22882ca2ba6 100644
--- a/tests/ui/closures/binder/disallow-ty.stderr
+++ b/tests/ui/closures/binder/disallow-ty.stderr
@@ -1,8 +1,12 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/disallow-ty.rs:4:9
|
LL | for<T> || -> () {};
| ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr
index 4d6560e96e5..69b0f741156 100644
--- a/tests/ui/conditional-compilation/cfg-generic-params.stderr
+++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr
@@ -1,21 +1,3 @@
-error: only lifetime parameters can be used in this context
- --> $DIR/cfg-generic-params.rs:7:45
- |
-LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
- | ^
-
-error: only lifetime parameters can be used in this context
- --> $DIR/cfg-generic-params.rs:11:51
- |
-LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
- | ^
-
-error: only lifetime parameters can be used in this context
- --> $DIR/cfg-generic-params.rs:15:54
- |
-LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
- | ^
-
error: cannot find attribute `unknown` in this scope
--> $DIR/cfg-generic-params.rs:19:29
|
@@ -46,5 +28,33 @@ error: cannot find attribute `unknown` in this scope
LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
| ^^^^^^^
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/cfg-generic-params.rs:7:45
+ |
+LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn();
+ | ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/cfg-generic-params.rs:11:51
+ |
+LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy;
+ | ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/cfg-generic-params.rs:15:54
+ |
+LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
+ | ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
error: aborting due to 8 previous errors
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
new file mode 100644
index 00000000000..221e9133fcc
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.rs
@@ -0,0 +1,4 @@
+fn foo() where for<T> T:, {}
+//~^ ERROR only lifetime parameters can be used in this context
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
new file mode 100644
index 00000000000..75645e32401
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-non_lifetime_binders.stderr
@@ -0,0 +1,12 @@
+error[E0658]: only lifetime parameters can be used in this context
+ --> $DIR/feature-gate-non_lifetime_binders.rs:1:20
+ |
+LL | fn foo() where for<T> T:, {}
+ | ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
index f31aa554634..d605c9e0df7 100644
--- a/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
+++ b/tests/ui/higher-rank-trait-bounds/hrtb-wrong-kind.stderr
@@ -1,14 +1,21 @@
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/hrtb-wrong-kind.rs:1:18
|
LL | fn a() where for<T> T: Copy {}
| ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
-error: only lifetime parameters can be used in this context
+error[E0658]: only lifetime parameters can be used in this context
--> $DIR/hrtb-wrong-kind.rs:4:24
|
LL | fn b() where for<const C: usize> [(); C]: Copy {}
| ^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/parser/recover-fn-ptr-with-generics.stderr b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
index 1da9c18571b..069fcffe9a0 100644
--- a/tests/ui/parser/recover-fn-ptr-with-generics.stderr
+++ b/tests/ui/parser/recover-fn-ptr-with-generics.stderr
@@ -88,12 +88,6 @@ error: expected identifier, found `>`
LL | type QuiteBroken = fn<const>();
| ^ expected identifier
-error: lifetime bounds cannot be used in this context
- --> $DIR/recover-fn-ptr-with-generics.rs:22:26
- |
-LL | let _: extern fn<'a: 'static>();
- | ^^^^^^^
-
error[E0412]: cannot find type `T` in this scope
--> $DIR/recover-fn-ptr-with-generics.rs:5:27
|
@@ -106,6 +100,12 @@ error[E0412]: cannot find type `T` in this scope
LL | type Identity = fn<T>(T) -> T;
| ^ not found in this scope
+error: lifetime bounds cannot be used in this context
+ --> $DIR/recover-fn-ptr-with-generics.rs:22:26
+ |
+LL | let _: extern fn<'a: 'static>();
+ | ^^^^^^^
+
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs
new file mode 100644
index 00000000000..a797aae65db
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.rs
@@ -0,0 +1,19 @@
+// check-pass
+// Basic test that show's we can succesfully typeck a `for<T>` where clause.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+impl<T: ?Sized> Trait for T {}
+
+fn foo()
+where
+ for<T> T: Trait,
+{
+}
+
+fn main() {
+ foo();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr
new file mode 100644
index 00000000000..fddc5d9fc25
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/basic.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/basic.rs:4:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs
new file mode 100644
index 00000000000..460f68907e8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.rs
@@ -0,0 +1,23 @@
+// Error reporting for where `for<T> T: Trait` doesn't hold
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Trait {}
+
+fn fail()
+where
+ for<T> T: Trait,
+{}
+
+fn auto_trait()
+where
+ for<T> T: Send,
+{}
+
+fn main() {
+ fail();
+ //~^ ERROR the trait bound `T: Trait` is not satisfied
+ auto_trait();
+ //~^ ERROR `T` cannot be sent between threads safely
+}
diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr
new file mode 100644
index 00000000000..ba5953193a4
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/fail.stderr
@@ -0,0 +1,43 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/fail.rs:3:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+ --> $DIR/fail.rs:19:5
+ |
+LL | fail();
+ | ^^^^ the trait `Trait` is not implemented for `T`
+ |
+note: required by a bound in `fail`
+ --> $DIR/fail.rs:10:15
+ |
+LL | fn fail()
+ | ---- required by a bound in this
+LL | where
+LL | for<T> T: Trait,
+ | ^^^^^ required by this bound in `fail`
+
+error[E0277]: `T` cannot be sent between threads safely
+ --> $DIR/fail.rs:21:5
+ |
+LL | auto_trait();
+ | ^^^^^^^^^^ `T` cannot be sent between threads safely
+ |
+ = help: the trait `Send` is not implemented for `T`
+note: required by a bound in `auto_trait`
+ --> $DIR/fail.rs:15:15
+ |
+LL | fn auto_trait()
+ | ---------- required by a bound in this
+LL | where
+LL | for<T> T: Send,
+ | ^^^^ required by this bound in `auto_trait`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
new file mode 100644
index 00000000000..8fb7dd27605
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic dyn trait.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Test<T> {}
+
+fn foo() -> &'static dyn for<T> Test<T> {
+ //~^ ERROR late-bound type parameter not allowed on trait object types
+ todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr
new file mode 100644
index 00000000000..44071107de4
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-dyn.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/on-dyn.rs:3:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on trait object types
+ --> $DIR/on-dyn.rs:8:30
+ |
+LL | fn foo() -> &'static dyn for<T> Test<T> {
+ | ^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
new file mode 100644
index 00000000000..0aaff52b6d8
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs
@@ -0,0 +1,13 @@
+// Tests to make sure that we reject polymorphic fn ptrs.
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn foo() -> for<T> fn(T) {
+ //~^ ERROR late-bound type parameter not allowed on function pointer types
+ todo!()
+}
+
+fn main() {
+ foo()(1i32);
+}
diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr
new file mode 100644
index 00000000000..bb7dccaf07d
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/on-ptr.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/on-ptr.rs:3:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: late-bound type parameter not allowed on function pointer types
+ --> $DIR/on-ptr.rs:6:17
+ |
+LL | fn foo() -> for<T> fn(T) {
+ | ^
+
+error: aborting due to previous error; 1 warning emitted
+