Skip to content

Add GenericArgKind::as_{type,const,region} #110545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{
self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility,
};
Expand Down Expand Up @@ -1182,23 +1181,21 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>(
let names = get_parameter_names(cx, generics);
let template_params: SmallVec<_> = iter::zip(substs, names)
.filter_map(|(kind, name)| {
if let GenericArgKind::Type(ty) = kind.unpack() {
kind.as_type().map(|ty| {
let actual_type =
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
let actual_type_di_node = type_di_node(cx, actual_type);
let name = name.as_str();
Some(unsafe {
unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
None,
name.as_ptr().cast(),
name.len(),
actual_type_di_node,
)
})
} else {
None
}
}
})
})
.collect();

Expand Down
12 changes: 5 additions & 7 deletions compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_index::vec::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt};
use rustc_session::config::{self, DebugInfo};
use rustc_session::Session;
Expand Down Expand Up @@ -461,23 +461,21 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let names = get_parameter_names(cx, generics);
iter::zip(substs, names)
.filter_map(|(kind, name)| {
if let GenericArgKind::Type(ty) = kind.unpack() {
kind.as_type().map(|ty| {
let actual_type =
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
let actual_type_metadata = type_di_node(cx, actual_type);
let name = name.as_str();
Some(unsafe {
unsafe {
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
None,
name.as_ptr().cast(),
name.len(),
actual_type_metadata,
))
})
} else {
None
}
}
})
})
.collect()
} else {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_codegen_ssa/src/meth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ impl<'a, 'tcx> VirtualIndex {
/// ref of the type.
fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> {
for arg in ty.peel_refs().walk() {
if let GenericArgKind::Type(ty) = arg.unpack() {
if let ty::Dynamic(data, _, _) = ty.kind() {
return data.principal().expect("expected principal trait object");
}
if let GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Dynamic(data, _, _) = ty.kind()
{
return data.principal().expect("expected principal trait object");
}
}

Expand Down
25 changes: 8 additions & 17 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use rustc_infer::infer;
use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::Session;
use rustc_span::symbol::Ident;
Expand Down Expand Up @@ -250,16 +249,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
}

fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
if let Some(param) = param {
if let GenericArgKind::Type(ty) = self.var_for_def(span, param).unpack() {
return ty;
}
unreachable!()
} else {
self.next_ty_var(TypeVariableOrigin {
match param {
Some(param) => self.var_for_def(span, param).as_type().unwrap(),
None => self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
})
}),
}
}

Expand All @@ -269,16 +264,12 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
param: Option<&ty::GenericParamDef>,
span: Span,
) -> Const<'tcx> {
if let Some(param) = param {
if let GenericArgKind::Const(ct) = self.var_for_def(span, param).unpack() {
return ct;
}
unreachable!()
} else {
self.next_const_var(
match param {
Some(param) => self.var_for_def(span, param).as_const().unwrap(),
None => self.next_const_var(
ty,
ConstVariableOrigin { kind: ConstVariableOriginKind::ConstInference, span },
)
),
}
}

Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,8 @@ declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
impl BoxPointers {
fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
for leaf in ty.walk() {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
if leaf_ty.is_box() {
cx.emit_spanned_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
}
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() && leaf_ty.is_box() {
cx.emit_spanned_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
}
}
}
Expand Down
70 changes: 35 additions & 35 deletions compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,30 +180,45 @@ impl<'tcx> GenericArg<'tcx> {
}
}

/// Unpack the `GenericArg` as a region when it is known certainly to be a region.
pub fn expect_region(self) -> ty::Region<'tcx> {
#[inline]
pub fn as_type(self) -> Option<Ty<'tcx>> {
match self.unpack() {
GenericArgKind::Type(ty) => Some(ty),
_ => None,
}
}

#[inline]
pub fn as_region(self) -> Option<ty::Region<'tcx>> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt,
_ => bug!("expected a region, but found another kind"),
GenericArgKind::Lifetime(re) => Some(re),
_ => None,
}
}

#[inline]
pub fn as_const(self) -> Option<ty::Const<'tcx>> {
match self.unpack() {
GenericArgKind::Const(ct) => Some(ct),
_ => None,
}
}

/// Unpack the `GenericArg` as a region when it is known certainly to be a region.
pub fn expect_region(self) -> ty::Region<'tcx> {
self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind"))
}

/// Unpack the `GenericArg` as a type when it is known certainly to be a type.
/// This is true in cases where `Substs` is used in places where the kinds are known
/// to be limited (e.g. in tuples, where the only parameters are type parameters).
pub fn expect_ty(self) -> Ty<'tcx> {
match self.unpack() {
GenericArgKind::Type(ty) => ty,
_ => bug!("expected a type, but found another kind"),
}
self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind"))
}

/// Unpack the `GenericArg` as a const when it is known certainly to be a const.
pub fn expect_const(self) -> ty::Const<'tcx> {
match self.unpack() {
GenericArgKind::Const(c) => c,
_ => bug!("expected a const, but found another kind"),
}
self.as_const().unwrap_or_else(|| bug!("expected a const, but found another kind"))
}

pub fn is_non_region_infer(self) -> bool {
Expand Down Expand Up @@ -379,22 +394,17 @@ impl<'tcx> InternalSubsts<'tcx> {

#[inline]
pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
self.iter()
.filter_map(|k| if let GenericArgKind::Type(ty) = k.unpack() { Some(ty) } else { None })
self.iter().filter_map(|k| k.as_type())
}

#[inline]
pub fn regions(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'tcx {
self.iter().filter_map(|k| {
if let GenericArgKind::Lifetime(lt) = k.unpack() { Some(lt) } else { None }
})
self.iter().filter_map(|k| k.as_region())
}

#[inline]
pub fn consts(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'tcx {
self.iter().filter_map(|k| {
if let GenericArgKind::Const(ct) = k.unpack() { Some(ct) } else { None }
})
self.iter().filter_map(|k| k.as_const())
}

#[inline]
Expand All @@ -410,31 +420,21 @@ impl<'tcx> InternalSubsts<'tcx> {
#[inline]
#[track_caller]
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
if let GenericArgKind::Type(ty) = self[i].unpack() {
ty
} else {
bug!("expected type for param #{} in {:?}", i, self);
}
self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self))
}

#[inline]
#[track_caller]
pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
lt
} else {
bug!("expected region for param #{} in {:?}", i, self);
}
self[i]
.as_region()
.unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self))
}

#[inline]
#[track_caller]
pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
if let GenericArgKind::Const(ct) = self[i].unpack() {
ct
} else {
bug!("expected const for param #{} in {:?}", i, self);
}
self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self))
}

#[inline]
Expand Down
48 changes: 22 additions & 26 deletions compiler/rustc_mir_transform/src/function_item_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, EarlyBinder, GenericArgKind, PredicateKind, SubstsRef, Ty, TyCtxt};
use rustc_middle::ty::{self, EarlyBinder, PredicateKind, SubstsRef, Ty, TyCtxt};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::{symbol::sym, Span};
use rustc_target::spec::abi::Abi;
Expand Down Expand Up @@ -45,14 +45,12 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
// Handle calls to `transmute`
if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
let arg_ty = args[0].ty(self.body, self.tcx);
for generic_inner_ty in arg_ty.walk() {
if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
if let Some((fn_id, fn_substs)) =
FunctionItemRefChecker::is_fn_ref(inner_ty)
{
let span = self.nth_arg_span(&args, 0);
self.emit_lint(fn_id, fn_substs, source_info, span);
}
for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) {
if let Some((fn_id, fn_substs)) =
FunctionItemRefChecker::is_fn_ref(inner_ty)
{
let span = self.nth_arg_span(&args, 0);
self.emit_lint(fn_id, fn_substs, source_info, span);
}
}
} else {
Expand Down Expand Up @@ -82,24 +80,22 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs();
for (arg_num, arg_def) in arg_defs.iter().enumerate() {
// For all types reachable from the argument type in the fn sig
for generic_inner_ty in arg_def.walk() {
if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
// If the inner type matches the type bound by `Pointer`
if inner_ty == bound_ty {
// Do a substitution using the parameters from the callsite
let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
if let Some((fn_id, fn_substs)) =
FunctionItemRefChecker::is_fn_ref(subst_ty)
{
let mut span = self.nth_arg_span(args, arg_num);
if span.from_expansion() {
// The operand's ctxt wouldn't display the lint since it's inside a macro so
// we have to use the callsite's ctxt.
let callsite_ctxt = span.source_callsite().ctxt();
span = span.with_ctxt(callsite_ctxt);
}
self.emit_lint(fn_id, fn_substs, source_info, span);
for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) {
// If the inner type matches the type bound by `Pointer`
if inner_ty == bound_ty {
// Do a substitution using the parameters from the callsite
let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
if let Some((fn_id, fn_substs)) =
FunctionItemRefChecker::is_fn_ref(subst_ty)
{
let mut span = self.nth_arg_span(args, arg_num);
if span.from_expansion() {
// The operand's ctxt wouldn't display the lint since it's inside a macro so
// we have to use the callsite's ctxt.
let callsite_ctxt = span.source_callsite().ctxt();
span = span.with_ctxt(callsite_ctxt);
}
self.emit_lint(fn_id, fn_substs, source_info, span);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -814,16 +814,10 @@ fn transform_substs<'tcx>(
substs: SubstsRef<'tcx>,
options: TransformTyOptions,
) -> SubstsRef<'tcx> {
let substs = substs.iter().map(|subst| {
if let GenericArgKind::Type(ty) = subst.unpack() {
if is_c_void_ty(tcx, ty) {
tcx.mk_unit().into()
} else {
transform_ty(tcx, ty, options).into()
}
} else {
subst
}
let substs = substs.iter().map(|subst| match subst.unpack() {
GenericArgKind::Type(ty) if is_c_void_ty(tcx, ty) => tcx.mk_unit().into(),
GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
_ => subst,
});
tcx.mk_substs_from_iter(substs)
}
Expand Down