]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / compiler / rustc_hir_analysis / src / collect / resolve_bound_vars.rs
index 6dd0c840de632e5db32d4b01c6266f0973cdd10a..eb4466449a09f8faa3e03221ce85b44d1edf87f7 100644 (file)
@@ -158,13 +158,14 @@ enum Scope<'a> {
         s: ScopeRef<'a>,
     },
 
-    /// Disallows capturing non-lifetime binders from parent scopes.
+    /// Disallows capturing late-bound vars from parent scopes.
     ///
     /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
     /// since we don't do something more correct like replacing any captured
     /// late-bound vars with early-bound params in the const's own generics.
-    AnonConstBoundary {
+    LateBoundary {
         s: ScopeRef<'a>,
+        what: &'static str,
     },
 
     Root {
@@ -216,7 +217,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("s", &"..")
                 .finish(),
             Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
-            Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
+            Scope::LateBoundary { s: _, what } => {
+                f.debug_struct("LateBoundary").field("what", what).finish()
+            }
             Scope::Root { opt_parent_item } => {
                 f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
             }
@@ -318,7 +321,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     break (vec![], BinderScopeType::Normal);
                 }
 
-                Scope::ObjectLifetimeDefault { s, .. } | Scope::AnonConstBoundary { s } => {
+                Scope::ObjectLifetimeDefault { s, .. } | Scope::LateBoundary { s, .. } => {
                     scope = s;
                 }
 
@@ -697,9 +700,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     }) => {
                         intravisit::walk_ty(self, ty);
 
-                        // Elided lifetimes are not allowed in non-return
-                        // position impl Trait
-                        let scope = Scope::TraitRefBoundary { s: self.scope };
+                        // Elided lifetimes and late-bound lifetimes (from the parent)
+                        // are not allowed in non-return position impl Trait
+                        let scope = Scope::LateBoundary {
+                            s: &Scope::TraitRefBoundary { s: self.scope },
+                            what: "type alias impl trait",
+                        };
                         self.with(scope, |this| intravisit::walk_item(this, opaque_ty));
 
                         return;
@@ -849,106 +855,87 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
         let scope = Scope::TraitRefBoundary { s: self.scope };
         self.with(scope, |this| {
-            for param in generics.params {
-                match param.kind {
-                    GenericParamKind::Lifetime { .. } => {}
-                    GenericParamKind::Type { default, .. } => {
-                        if let Some(ty) = default {
-                            this.visit_ty(ty);
-                        }
-                    }
-                    GenericParamKind::Const { ty, default } => {
-                        this.visit_ty(ty);
-                        if let Some(default) = default {
-                            this.visit_body(this.tcx.hir().body(default.body));
-                        }
-                    }
-                }
+            walk_list!(this, visit_generic_param, generics.params);
+            walk_list!(this, visit_where_predicate, generics.predicates);
+        })
+    }
+
+    fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
+        match predicate {
+            &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                hir_id,
+                bounded_ty,
+                bounds,
+                bound_generic_params,
+                origin,
+                ..
+            }) => {
+                let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
+                    bound_generic_params
+                        .iter()
+                        .enumerate()
+                        .map(|(late_bound_idx, param)| {
+                            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(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
+                // will be `Concatenating` anyways, so we don't have to worry about the depth
+                // being wrong.
+                let scope = Scope::Binder {
+                    hir_id,
+                    bound_vars,
+                    s: self.scope,
+                    scope_type: BinderScopeType::Normal,
+                    where_bound_origin: Some(origin),
+                };
+                self.with(scope, |this| {
+                    walk_list!(this, visit_generic_param, bound_generic_params);
+                    this.visit_ty(&bounded_ty);
+                    walk_list!(this, visit_param_bound, bounds);
+                })
             }
-            for predicate in generics.predicates {
-                match predicate {
-                    &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                        hir_id,
-                        bounded_ty,
-                        bounds,
-                        bound_generic_params,
-                        origin,
-                        ..
-                    }) => {
-                        let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
-                            bound_generic_params
-                                .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
-                        // will be `Concatenating` anyways, so we don't have to worry about the depth
-                        // being wrong.
-                        let scope = Scope::Binder {
-                            hir_id,
-                            bound_vars,
-                            s: this.scope,
-                            scope_type: BinderScopeType::Normal,
-                            where_bound_origin: Some(origin),
+            &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                lifetime,
+                bounds,
+                ..
+            }) => {
+                self.visit_lifetime(lifetime);
+                walk_list!(self, visit_param_bound, bounds);
+
+                if lifetime.res != hir::LifetimeName::Static {
+                    for bound in bounds {
+                        let hir::GenericBound::Outlives(lt) = bound else {
+                            continue;
                         };
-                        this.with(scope, |this| {
-                            this.visit_ty(&bounded_ty);
-                            walk_list!(this, visit_param_bound, bounds);
-                        })
-                    }
-                    &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
-                        lifetime,
-                        bounds,
-                        ..
-                    }) => {
-                        this.visit_lifetime(lifetime);
-                        walk_list!(this, visit_param_bound, bounds);
-
-                        if lifetime.res != hir::LifetimeName::Static {
-                            for bound in bounds {
-                                let hir::GenericBound::Outlives(lt) = bound else {
-                                    continue;
-                                };
-                                if lt.res != hir::LifetimeName::Static {
-                                    continue;
-                                }
-                                this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
-                                this.tcx.struct_span_lint_hir(
-                                    lint::builtin::UNUSED_LIFETIMES,
-                                    lifetime.hir_id,
-                                    lifetime.ident.span,
-                                    format!(
-                                        "unnecessary lifetime parameter `{}`",
-                                        lifetime.ident
-                                    ),
-                                    |lint| {
-                                        let help = format!(
-                                            "you can use the `'static` lifetime directly, in place of `{}`",
-                                            lifetime.ident,
-                                        );
-                                        lint.help(help)
-                                    },
-                                );
-                            }
+                        if lt.res != hir::LifetimeName::Static {
+                            continue;
                         }
-                    }
-                    &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
-                        lhs_ty,
-                        rhs_ty,
-                        ..
-                    }) => {
-                        this.visit_ty(lhs_ty);
-                        this.visit_ty(rhs_ty);
+                        self.insert_lifetime(lt, ResolvedArg::StaticLifetime);
+                        self.tcx.struct_span_lint_hir(
+                            lint::builtin::UNUSED_LIFETIMES,
+                            lifetime.hir_id,
+                            lifetime.ident.span,
+                            format!("unnecessary lifetime parameter `{}`", lifetime.ident),
+                            |lint| {
+                                let help = format!(
+                                    "you can use the `'static` lifetime directly, in place of `{}`",
+                                    lifetime.ident,
+                                );
+                                lint.help(help)
+                            },
+                        );
                     }
                 }
             }
-        })
+            &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
+                self.visit_ty(lhs_ty);
+                self.visit_ty(rhs_ty);
+            }
+        }
     }
 
     fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
@@ -982,10 +969,37 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     }
 
     fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
-        self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
+        self.with(Scope::LateBoundary { s: self.scope, what: "constant" }, |this| {
             intravisit::walk_anon_const(this, c);
         });
     }
+
+    fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
+        match p.kind {
+            GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
+                self.resolve_type_ref(p.def_id, p.hir_id);
+            }
+            GenericParamKind::Lifetime { .. } => {
+                // No need to resolve lifetime params, we don't use them for things
+                // like implicit `?Sized` or const-param-has-ty predicates.
+            }
+        }
+
+        match p.kind {
+            GenericParamKind::Lifetime { .. } => {}
+            GenericParamKind::Type { default, .. } => {
+                if let Some(ty) = default {
+                    self.visit_ty(ty);
+                }
+            }
+            GenericParamKind::Const { ty, default } => {
+                self.visit_ty(ty);
+                if let Some(default) = default {
+                    self.visit_body(self.tcx.hir().body(default.body));
+                }
+            }
+        }
+    }
 }
 
 fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
@@ -1165,6 +1179,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let mut late_depth = 0;
         let mut scope = self.scope;
         let mut outermost_body = None;
+        let mut crossed_late_boundary = None;
         let result = loop {
             match *scope {
                 Scope::Body { id, s } => {
@@ -1197,7 +1212,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
                         && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
                         && param.is_elided_lifetime()
-                        && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
+                        && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
                         && !self.tcx.features().anonymous_lifetime_in_impl_trait
                     {
                         let mut diag =  rustc_session::parse::feature_err(
@@ -1249,8 +1264,12 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
                 Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
-                | Scope::TraitRefBoundary { s, .. }
-                | Scope::AnonConstBoundary { s } => {
+                | Scope::TraitRefBoundary { s, .. } => {
+                    scope = s;
+                }
+
+                Scope::LateBoundary { s, what } => {
+                    crossed_late_boundary = Some(what);
                     scope = s;
                 }
             }
@@ -1259,6 +1278,22 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         if let Some(mut def) = result {
             if let ResolvedArg::EarlyBound(..) = def {
                 // Do not free early-bound regions, only late-bound ones.
+            } else if let ResolvedArg::LateBound(_, _, param_def_id) = def
+                && let Some(what) = crossed_late_boundary
+            {
+                let use_span = lifetime_ref.ident.span;
+                let def_span = self.tcx.def_span(param_def_id);
+                let guar = match self.tcx.def_kind(param_def_id) {
+                    DefKind::LifetimeParam => {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBound::Lifetime {
+                            use_span,
+                            def_span,
+                            what,
+                        })
+                    }
+                    _ => unreachable!(),
+                };
+                def = ResolvedArg::Error(guar);
             } else if let Some(body_id) = outermost_body {
                 let fn_id = self.tcx.hir().body_owner(body_id);
                 match self.tcx.hir().get(fn_id) {
@@ -1313,7 +1348,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. }
-                | Scope::AnonConstBoundary { s } => {
+                | Scope::LateBoundary { s, .. } => {
                     scope = s;
                 }
             }
@@ -1332,7 +1367,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         // search.
         let mut late_depth = 0;
         let mut scope = self.scope;
-        let mut crossed_anon_const = false;
+        let mut crossed_late_boundary = None;
 
         let result = loop {
             match *scope {
@@ -1367,28 +1402,32 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     scope = s;
                 }
 
-                Scope::AnonConstBoundary { s } => {
-                    crossed_anon_const = true;
+                Scope::LateBoundary { s, what } => {
+                    crossed_late_boundary = Some(what);
                     scope = s;
                 }
             }
         };
 
         if let Some(def) = result {
-            if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
+            if let ResolvedArg::LateBound(..) = def
+                && let Some(what) = crossed_late_boundary
+            {
                 let use_span = self.tcx.hir().span(hir_id);
                 let def_span = self.tcx.def_span(param_def_id);
                 let guar = match self.tcx.def_kind(param_def_id) {
                     DefKind::ConstParam => {
-                        self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBound::Const {
                             use_span,
                             def_span,
+                            what,
                         })
                     }
                     DefKind::TyParam => {
-                        self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBound::Type {
                             use_span,
                             def_span,
+                            what,
                         })
                     }
                     _ => unreachable!(),
@@ -1437,7 +1476,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. }
-                | Scope::AnonConstBoundary { s } => {
+                | Scope::LateBoundary { s, .. } => {
                     scope = s;
                 }
             }
@@ -1480,7 +1519,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 DefKind::Struct
                 | DefKind::Union
                 | DefKind::Enum
-                | DefKind::TyAlias { .. }
+                | DefKind::TyAlias
                 | DefKind::Trait,
                 def_id,
             ) if depth == 0 => Some(def_id),
@@ -1517,7 +1556,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         | Scope::ObjectLifetimeDefault { s, .. }
                         | Scope::Supertrait { s, .. }
                         | Scope::TraitRefBoundary { s, .. }
-                        | Scope::AnonConstBoundary { s } => {
+                        | Scope::LateBoundary { s, .. } => {
                             scope = s;
                         }
                     }
@@ -1822,7 +1861,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
                 Scope::Supertrait { s, .. }
                 | Scope::TraitRefBoundary { s, .. }
-                | Scope::AnonConstBoundary { s } => {
+                | Scope::LateBoundary { s, .. } => {
                     scope = s;
                 }
             }
@@ -1990,7 +2029,7 @@ fn is_late_bound_map(
 
                 hir::TyKind::Path(hir::QPath::Resolved(
                     None,
-                    hir::Path { res: Res::Def(DefKind::TyAlias { .. }, alias_def), segments, span },
+                    hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span },
                 )) => {
                     // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider
                     // args to be unconstrained.