about summary refs log tree commit diff
path: root/compiler/rustc_ast_lowering/src/lib.rs
diff options
context:
space:
mode:
authorDeadbeef <ent3rm4n@gmail.com>2023-07-25 05:58:53 +0000
committerDeadbeef <ent3rm4n@gmail.com>2023-08-06 13:34:53 +0000
commit92f4c59e4847005752a358ccacb5ae264700fbc4 (patch)
tree970aac1a96c706880388f8f10ba72f5421ccec74 /compiler/rustc_ast_lowering/src/lib.rs
parent4f7bb9890c0402cd145556ac1929d13d7524959e (diff)
downloadrust-92f4c59e4847005752a358ccacb5ae264700fbc4.tar.gz
rust-92f4c59e4847005752a358ccacb5ae264700fbc4.zip
lower impl const to bind to host effect param
Diffstat (limited to 'compiler/rustc_ast_lowering/src/lib.rs')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs85
1 files changed, 77 insertions, 8 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index ac750690046..dd081fafafb 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -142,6 +142,8 @@ struct LoweringContext<'a, 'hir> {
     /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
     /// field from the original parameter 'a to the new parameter 'a1.
     generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
+
+    host_param_id: Option<LocalDefId>,
 }
 
 trait ResolverAstLoweringExt {
@@ -1267,6 +1269,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: t.span
                     },
                     itctx,
+                    ast::Const::No,
                 );
                 let bounds = this.arena.alloc_from_iter([bound]);
                 let lifetime_bound = this.elided_dyn_bound(t.span);
@@ -1277,7 +1280,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         let id = self.lower_node_id(t.id);
-        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
+        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
         self.ty_path(id, t.span, qpath)
     }
 
@@ -1361,10 +1364,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
                             GenericBound::Trait(
                                 ty,
-                                TraitBoundModifier::None
+                                modifier @ (TraitBoundModifier::None
                                 | TraitBoundModifier::MaybeConst
-                                | TraitBoundModifier::Negative,
-                            ) => Some(this.lower_poly_trait_ref(ty, itctx)),
+                                | TraitBoundModifier::Negative),
+                            ) => {
+                                Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
+                            }
                             // `~const ?Bound` will cause an error during AST validation
                             // anyways, so treat it like `?Bound` as compilation proceeds.
                             GenericBound::Trait(
@@ -2189,7 +2194,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::GenericBound<'hir> {
         match tpb {
             GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
-                self.lower_poly_trait_ref(p, itctx),
+                self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
                 self.lower_trait_bound_modifier(*modifier),
             ),
             GenericBound::Outlives(lifetime) => {
@@ -2332,8 +2337,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
-        let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
+    fn lower_trait_ref(
+        &mut self,
+        constness: ast::Const,
+        p: &TraitRef,
+        itctx: &ImplTraitContext,
+    ) -> hir::TraitRef<'hir> {
+        let path = match self.lower_qpath(
+            p.ref_id,
+            &None,
+            &p.path,
+            ParamMode::Explicit,
+            itctx,
+            Some(constness),
+        ) {
             hir::QPath::Resolved(None, path) => path,
             qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
         };
@@ -2345,10 +2362,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         &mut self,
         p: &PolyTraitRef,
         itctx: &ImplTraitContext,
+        constness: ast::Const,
     ) -> hir::PolyTraitRef<'hir> {
         let bound_generic_params =
             self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
-        let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
+        let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
         hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
     }
 
@@ -2702,6 +2720,57 @@ struct GenericArgsCtor<'hir> {
 }
 
 impl<'hir> GenericArgsCtor<'hir> {
+    fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
+        if !lcx.tcx.features().effects {
+            return;
+        }
+
+        // if bound is non-const, don't add host effect param
+        let ast::Const::Yes(span) = constness else { return };
+
+        let span = lcx.lower_span(span);
+
+        let id = lcx.next_node_id();
+        let hir_id = lcx.next_id();
+        let body = lcx.lower_body(|lcx| {
+            (
+                &[],
+                match constness {
+                    ast::Const::Yes(_) => {
+                        let hir_id = lcx.next_id();
+                        let res =
+                            Res::Def(DefKind::ConstParam, lcx.host_param_id.unwrap().to_def_id());
+                        let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved(
+                            None,
+                            lcx.arena.alloc(hir::Path {
+                                span,
+                                res,
+                                segments: arena_vec![lcx; hir::PathSegment::new(Ident {
+                                        name: sym::host,
+                                        span,
+                                    }, hir_id, res)],
+                            }),
+                        ));
+                        lcx.expr(span, expr_kind)
+                    }
+                    ast::Const::No => lcx.expr(
+                        span,
+                        hir::ExprKind::Lit(
+                            lcx.arena.alloc(hir::Lit { span, node: ast::LitKind::Bool(true) }),
+                        ),
+                    ),
+                },
+            )
+        });
+        let def_id =
+            lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span);
+        lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
+        self.args.push(hir::GenericArg::Const(hir::ConstArg {
+            value: hir::AnonConst { def_id, hir_id, body },
+            span,
+        }))
+    }
+
     fn is_empty(&self) -> bool {
         self.args.is_empty()
             && self.bindings.is_empty()