Skip to content

rewrite ensure_drop_params_and_item_params_correspond #95309

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 5 commits into from
May 20, 2022
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
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ pub struct InferCtxtInner<'tcx> {
///
/// Before running `resolve_regions_and_report_errors`, the creator
/// of the inference context is expected to invoke
/// `process_region_obligations` (defined in `self::region_obligations`)
/// [`InferCtxt::process_registered_region_obligations`]
/// for each body-id in this map, which will process the
/// obligations within. This is expected to be done 'late enough'
/// that all type inference variables have been bound and so forth.
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
///
/// # Parameters
///
/// - `region_bound_pairs`: the set of region bounds implied by
/// - `region_bound_pairs_map`: the set of region bounds implied by
/// the parameters and where-clauses. In particular, each pair
/// `('a, K)` in this list tells us that the bounds in scope
/// indicate that `K: 'a`, where `K` is either a generic
Expand All @@ -147,12 +147,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
/// - `param_env` is the parameter environment for the enclosing function.
/// - `body_id` is the body-id whose region obligations are being
/// processed.
///
/// # Returns
///
/// This function may have to perform normalizations, and hence it
/// returns an `InferOk` with subobligations that must be
/// processed.
#[instrument(level = "debug", skip(self, region_bound_pairs_map))]
pub fn process_registered_region_obligations(
&self,
Expand Down
124 changes: 92 additions & 32 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFolder};
use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt;
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
use crate::ty::{
self, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*,
TypeFoldable,
};
use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
use rustc_apfloat::Float as _;
use rustc_ast as ast;
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
Expand All @@ -18,6 +15,7 @@ use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::GrowableBitSet;
use rustc_macros::HashStable;
use rustc_span::{sym, DUMMY_SP};
use rustc_target::abi::{Integer, Size, TargetDataLayout};
Expand All @@ -32,6 +30,19 @@ pub struct Discr<'tcx> {
pub ty: Ty<'tcx>,
}

/// Used as an input to [`TyCtxt::uses_unique_generic_params`].
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum IgnoreRegions {
Yes,
No,
}

#[derive(Copy, Clone, Debug)]
pub enum NotUniqueParam<'tcx> {
DuplicateParam(ty::GenericArg<'tcx>),
NotParam(ty::GenericArg<'tcx>),
}

impl<'tcx> fmt::Display for Discr<'tcx> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self.ty.kind() {
Expand All @@ -49,8 +60,8 @@ impl<'tcx> fmt::Display for Discr<'tcx> {

fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
let (int, signed) = match *ty.kind() {
Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
_ => bug!("non integer discriminant"),
};
(int.size(), signed)
Expand Down Expand Up @@ -176,7 +187,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let ty::Adt(def, substs) = *ty.kind() {
for field in def.all_fields() {
let field_ty = field.ty(self, substs);
if let Error(_) = field_ty.kind() {
if let ty::Error(_) = field_ty.kind() {
return true;
}
}
Expand Down Expand Up @@ -311,7 +322,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (mut a, mut b) = (source, target);
loop {
match (&a.kind(), &b.kind()) {
(&Adt(a_def, a_substs), &Adt(b_def, b_substs))
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() =>
{
if let Some(f) = a_def.non_enum_variant().fields.last() {
Expand All @@ -321,7 +332,7 @@ impl<'tcx> TyCtxt<'tcx> {
break;
}
}
(&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => {
(&ty::Tuple(a_tys), &ty::Tuple(b_tys)) if a_tys.len() == b_tys.len() => {
if let Some(&a_last) = a_tys.last() {
a = a_last;
b = *b_tys.last().unwrap();
Expand Down Expand Up @@ -427,7 +438,7 @@ impl<'tcx> TyCtxt<'tcx> {
.filter(|&(_, k)| {
match k.unpack() {
GenericArgKind::Lifetime(region) => match region.kind() {
ReEarlyBound(ref ebr) => {
ty::ReEarlyBound(ref ebr) => {
!impl_generics.region_param(ebr, self).pure_wrt_drop
}
// Error: not a region param
Expand All @@ -453,6 +464,47 @@ impl<'tcx> TyCtxt<'tcx> {
result
}

/// Checks whether each generic argument is simply a unique generic parameter.
pub fn uses_unique_generic_params(
self,
substs: SubstsRef<'tcx>,
ignore_regions: IgnoreRegions,
) -> Result<(), NotUniqueParam<'tcx>> {
let mut seen = GrowableBitSet::default();
for arg in substs {
match arg.unpack() {
GenericArgKind::Lifetime(lt) => {
if ignore_regions == IgnoreRegions::No {
let ty::ReEarlyBound(p) = lt.kind() else {
return Err(NotUniqueParam::NotParam(lt.into()))
};
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
}
GenericArgKind::Type(t) => match t.kind() {
ty::Param(p) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(t.into()));
}
}
_ => return Err(NotUniqueParam::NotParam(t.into())),
},
GenericArgKind::Const(c) => match c.val() {
ty::ConstKind::Param(p) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(c.into()));
}
}
_ => return Err(NotUniqueParam::NotParam(c.into())),
},
}
}

Ok(())
}

/// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
/// that closures have a `DefId`, but the closure *expression* also
/// has a `HirId` that is located within the context where the
Expand Down Expand Up @@ -594,30 +646,33 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}

pub fn bound_type_of(self, def_id: DefId) -> EarlyBinder<Ty<'tcx>> {
EarlyBinder(self.type_of(def_id))
pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder(self.type_of(def_id))
}

pub fn bound_fn_sig(self, def_id: DefId) -> EarlyBinder<ty::PolyFnSig<'tcx>> {
EarlyBinder(self.fn_sig(def_id))
pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
ty::EarlyBinder(self.fn_sig(def_id))
}

pub fn bound_impl_trait_ref(self, def_id: DefId) -> Option<EarlyBinder<ty::TraitRef<'tcx>>> {
self.impl_trait_ref(def_id).map(|i| EarlyBinder(i))
pub fn bound_impl_trait_ref(
self,
def_id: DefId,
) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i))
}

pub fn bound_explicit_item_bounds(
self,
def_id: DefId,
) -> EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
EarlyBinder(self.explicit_item_bounds(def_id))
) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
ty::EarlyBinder(self.explicit_item_bounds(def_id))
}

pub fn bound_item_bounds(
self,
def_id: DefId,
) -> EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
EarlyBinder(self.item_bounds(def_id))
) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
ty::EarlyBinder(self.item_bounds(def_id))
}
}

Expand Down Expand Up @@ -930,35 +985,40 @@ impl<'tcx> Ty<'tcx> {
pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind() {
// Look for an impl of both `PartialStructuralEq` and `StructuralEq`.
Adt(..) => tcx.has_structural_eq_impls(self),
ty::Adt(..) => tcx.has_structural_eq_impls(self),

// Primitive types that satisfy `Eq`.
Bool | Char | Int(_) | Uint(_) | Str | Never => true,
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => true,

// Composite types that satisfy `Eq` when all of their fields do.
//
// Because this function is "shallow", we return `true` for these composites regardless
// of the type(s) contained within.
Ref(..) | Array(..) | Slice(_) | Tuple(..) => true,
ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true,

// Raw pointers use bitwise comparison.
RawPtr(_) | FnPtr(_) => true,
ty::RawPtr(_) | ty::FnPtr(_) => true,

// Floating point numbers are not `Eq`.
Float(_) => false,
ty::Float(_) => false,

// Conservatively return `false` for all others...

// Anonymous function types
FnDef(..) | Closure(..) | Dynamic(..) | Generator(..) => false,
ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Generator(..) => false,

// Generic or inferred types
//
// FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
// called for known, fully-monomorphized types.
Projection(_) | Opaque(..) | Param(_) | Bound(..) | Placeholder(_) | Infer(_) => false,
ty::Projection(_)
| ty::Opaque(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => false,

Foreign(_) | GeneratorWitness(..) | Error(_) => false,
ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
}
}

Expand All @@ -974,13 +1034,13 @@ impl<'tcx> Ty<'tcx> {
/// - `&'a *const &'b u8 -> *const &'b u8`
pub fn peel_refs(self) -> Ty<'tcx> {
let mut ty = self;
while let Ref(_, inner_ty, _) = ty.kind() {
while let ty::Ref(_, inner_ty, _) = ty.kind() {
ty = *inner_ty;
}
ty
}

pub fn outer_exclusive_binder(self) -> DebruijnIndex {
pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex {
self.0.outer_exclusive_binder
}
}
Expand Down Expand Up @@ -1177,8 +1237,8 @@ pub struct AlwaysRequiresDrop;
/// with their underlying types.
pub fn normalize_opaque_types<'tcx>(
tcx: TyCtxt<'tcx>,
val: &'tcx List<ty::Predicate<'tcx>>,
) -> &'tcx List<ty::Predicate<'tcx>> {
val: &'tcx ty::List<ty::Predicate<'tcx>>,
) -> &'tcx ty::List<ty::Predicate<'tcx>> {
let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(),
Expand Down
Loading