about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs67
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
9 files changed, 90 insertions, 74 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 51194740450..590ade516ec 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,5 +1,3 @@
-use std::assert_matches::debug_assert_matches;
-
 use rustc_abi::FieldIdx;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxIndexSet;
@@ -21,6 +19,7 @@ pub struct InlineAsmCtxt<'a, 'tcx: 'a> {
     typing_env: ty::TypingEnv<'tcx>,
     target_features: &'tcx FxIndexSet<Symbol>,
     expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
+    node_ty: Box<dyn Fn(hir::HirId) -> Ty<'tcx> + 'a>,
 }
 
 enum NonAsmTypeReason<'tcx> {
@@ -35,13 +34,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         tcx: TyCtxt<'tcx>,
         def_id: LocalDefId,
         typing_env: ty::TypingEnv<'tcx>,
-        get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
+        expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
+        node_ty: impl Fn(hir::HirId) -> Ty<'tcx> + 'a,
     ) -> Self {
         InlineAsmCtxt {
             tcx,
             typing_env,
             target_features: tcx.asm_target_features(def_id),
-            expr_ty: Box::new(get_operand_ty),
+            expr_ty: Box::new(expr_ty),
+            node_ty: Box::new(node_ty),
         }
     }
 
@@ -49,6 +50,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         (self.expr_ty)(expr)
     }
 
+    fn node_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> {
+        (self.node_ty)(hir_id)
+    }
+
     // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
     fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
         // Type still may have region variables, but `Sized` does not depend
@@ -487,12 +492,23 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                         );
                     }
                 }
-                // Typeck has checked that Const operands are integers.
                 hir::InlineAsmOperand::Const { anon_const } => {
-                    debug_assert_matches!(
-                        self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
-                        ty::Error(_) | ty::Int(_) | ty::Uint(_)
-                    );
+                    let ty = self.node_ty(anon_const.hir_id);
+                    match ty.kind() {
+                        ty::Error(_) => {}
+                        _ if ty.is_integral() => {}
+                        _ => {
+                            self.tcx
+                                .dcx()
+                                .struct_span_err(op_sp, "invalid type for `const` operand")
+                                .with_span_label(
+                                    self.tcx.def_span(anon_const.def_id),
+                                    format!("is {} `{}`", ty.kind().article(), ty),
+                                )
+                                .with_help("`const` operands must be of an integer type")
+                                .emit();
+                        }
+                    }
                 }
                 // Typeck has checked that SymFn refers to a function.
                 hir::InlineAsmOperand::SymFn { expr } => {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index e6ea6eddcaa..d72cf00293f 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -966,7 +966,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
             let ty = tcx.type_of(param.def_id).instantiate_identity();
 
             if tcx.features().unsized_const_params() {
-                enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
+                enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
                     wfcx.register_bound(
                         ObligationCause::new(
                             hir_ty.span,
@@ -980,7 +980,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                     Ok(())
                 })
             } else if tcx.features().adt_const_params() {
-                enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
+                enter_wf_checking_ctxt(tcx, hir_ty.span, tcx.local_parent(param.def_id), |wfcx| {
                     wfcx.register_bound(
                         ObligationCause::new(
                             hir_ty.span,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 08d63f4349e..027aa5554a4 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1822,6 +1822,9 @@ fn const_param_default<'tcx>(
         ),
     };
     let icx = ItemCtxt::new(tcx, def_id);
-    let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id()));
+    let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
+    let ct = icx
+        .lowerer()
+        .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
     ty::EarlyBinder::bind(ct)
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 2cdd9a3a934..af1338e50d0 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -186,17 +186,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     {
                         Some(parent_did)
                     }
-                    // Exclude `GlobalAsm` here which cannot have generics.
-                    Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
-                        if asm.operands.iter().any(|(op, _op_sp)| match op {
-                            hir::InlineAsmOperand::Const { anon_const } => {
-                                anon_const.hir_id == hir_id
-                            }
-                            _ => false,
-                        }) =>
-                    {
-                        Some(parent_did)
-                    }
                     Node::TyPat(_) => Some(parent_did),
                     _ => None,
                 }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 5b511d27074..49549335363 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -223,10 +223,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             }
             hir::GenericParamKind::Const { .. } => {
                 let param_def_id = param.def_id.to_def_id();
-                let ct_ty = tcx
-                    .type_of(param_def_id)
-                    .no_bound_vars()
-                    .expect("const parameters cannot be generic");
+                let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
                 let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
                 predicates
                     .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index d564dc9699a..6936544838c 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -8,7 +8,7 @@ use rustc_middle::query::plumbing::CyclePlaceholder;
 use rustc_middle::ty::fold::fold_regions;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{DUMMY_SP, Ident, Span};
 
@@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
     let parent_node_id = tcx.parent_hir_id(hir_id);
     let parent_node = tcx.hir_node(parent_node_id);
 
-    let find_const = |&(op, op_sp)| match op {
-        hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
-            Some((anon_const, op_sp))
-        }
-        _ => None,
-    };
-
     match parent_node {
         // Anon consts "inside" the type system.
         Node::ConstArg(&ConstArg {
@@ -50,31 +43,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
             ..
         }) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
 
-        // Anon consts outside the type system.
-        Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
-        | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. })
-            if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
-        {
-            let ty = tcx.typeck(def_id).node_type(hir_id);
-
-            match ty.kind() {
-                ty::Error(_) => ty,
-                ty::Int(_) | ty::Uint(_) => ty,
-                _ => {
-                    let guar = tcx
-                        .dcx()
-                        .struct_span_err(op_sp, "invalid type for `const` operand")
-                        .with_span_label(
-                            tcx.def_span(anon_const.def_id),
-                            format!("is {} `{}`", ty.kind().article(), ty),
-                        )
-                        .with_help("`const` operands must be of an integer type")
-                        .emit();
-
-                    Ty::new_error(tcx, guar)
-                }
-            }
-        }
         Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
             tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
         }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 8d58a3bfbd3..fa58f12c553 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -273,7 +273,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
 
                             // We lower to an infer even when the feature gate is not enabled
                             // as it is useful for diagnostics to be able to see a `ConstKind::Infer`
-                            args.push(ctx.provided_kind(param, arg));
+                            args.push(ctx.provided_kind(&args, param, arg));
                             args_iter.next();
                             params.next();
                         }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 750770178ee..a0f848f07c4 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -232,12 +232,15 @@ impl AssocItemQSelf {
 /// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
 /// desired behavior.
 #[derive(Debug, Clone, Copy)]
-pub enum FeedConstTy {
+pub enum FeedConstTy<'a, 'tcx> {
     /// Feed the type.
     ///
     /// The `DefId` belongs to the const param that we are supplying
     /// this (anon) const arg to.
-    Param(DefId),
+    ///
+    /// The list of generic args is used to instantiate the parameters
+    /// used by the type of the const param specified by `DefId`.
+    Param(DefId, &'a [ty::GenericArg<'tcx>]),
     /// Don't feed the type.
     No,
 }
@@ -298,6 +301,7 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
 
     fn provided_kind(
         &mut self,
+        preceding_args: &[ty::GenericArg<'tcx>],
         param: &ty::GenericParamDef,
         arg: &GenericArg<'tcx>,
     ) -> ty::GenericArg<'tcx>;
@@ -481,6 +485,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             fn provided_kind(
                 &mut self,
+                preceding_args: &[ty::GenericArg<'tcx>],
                 param: &ty::GenericParamDef,
                 arg: &GenericArg<'tcx>,
             ) -> ty::GenericArg<'tcx> {
@@ -526,7 +531,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
                         .lowerer
                         // Ambig portions of `ConstArg` are handled in the match arm below
-                        .lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
+                        .lower_const_arg(
+                            ct.as_unambig_ct(),
+                            FeedConstTy::Param(param.def_id, preceding_args),
+                        )
                         .into(),
                     (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
                         self.lowerer.ct_infer(Some(param), inf.span).into()
@@ -582,8 +590,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         let ty = tcx
                             .at(self.span)
                             .type_of(param.def_id)
-                            .no_bound_vars()
-                            .expect("const parameter types cannot be generic");
+                            .instantiate(tcx, preceding_args);
                         if let Err(guar) = ty.error_reported() {
                             return ty::Const::new_error(tcx, guar).into();
                         }
@@ -2107,14 +2114,50 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     pub fn lower_const_arg(
         &self,
         const_arg: &hir::ConstArg<'tcx>,
-        feed: FeedConstTy,
+        feed: FeedConstTy<'_, 'tcx>,
     ) -> Const<'tcx> {
         let tcx = self.tcx();
 
-        if let FeedConstTy::Param(param_def_id) = feed
+        if let FeedConstTy::Param(param_def_id, args) = feed
             && let hir::ConstArgKind::Anon(anon) = &const_arg.kind
         {
-            tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
+            let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
+
+            // We must error if the instantiated type has any inference variables as we will
+            // use this type to feed the `type_of` and query results must not contain inference
+            // variables otherwise we will ICE.
+            //
+            // We also error if the type contains any regions as effectively any region will wind
+            // up as a region variable in mir borrowck. It would also be somewhat concerning if
+            // hir typeck was using equality but mir borrowck wound up using subtyping as that could
+            // result in a non-infer in hir typeck but a region variable in borrowck.
+            //
+            // FIXME(generic_const_parameter_types): Ideally we remove these errors one day when
+            // we have the ability to intermix typeck of anon const const args with the parent
+            // bodies typeck.
+            if tcx.features().generic_const_parameter_types()
+                && (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions())
+            {
+                let e = tcx.dcx().span_err(
+                    const_arg.span(),
+                    "anonymous constants with lifetimes in their type are not yet supported",
+                );
+                tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
+                return ty::Const::new_error(tcx, e);
+            }
+            if anon_const_type.has_non_region_infer() {
+                let e = tcx.dcx().span_err(
+                    const_arg.span(),
+                    "anonymous constants with inferred types are not yet supported",
+                );
+                tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
+                return ty::Const::new_error(tcx, e);
+            }
+
+            tcx.feed_anon_const_type(
+                anon.def_id,
+                ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)),
+            );
         }
 
         let hir_id = const_arg.hir_id;
@@ -2230,10 +2273,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let expr = &tcx.hir_body(anon.body).value;
         debug!(?expr);
 
-        let ty = tcx
-            .type_of(anon.def_id)
-            .no_bound_vars()
-            .expect("const parameter types cannot be generic");
+        // FIXME(generic_const_parameter_types): We should use the proper generic args
+        // here. It's only used as a hint for literals so doesn't matter too much to use the right
+        // generic arguments, just weaker type inference.
+        let ty = tcx.type_of(anon.def_id).instantiate_identity();
 
         match self.try_lower_anon_const_lit(ty, expr) {
             Some(v) => v,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index bdfbd540e40..cf18bab950a 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -260,7 +260,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
 pub fn lower_const_arg_for_rustdoc<'tcx>(
     tcx: TyCtxt<'tcx>,
     hir_ct: &hir::ConstArg<'tcx>,
-    feed: FeedConstTy,
+    feed: FeedConstTy<'_, 'tcx>,
 ) -> Const<'tcx> {
     let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
     collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)