Skip to content

Commit f3f6832

Browse files
committed
move unique param check into rustc_middle
1 parent 52cc779 commit f3f6832

File tree

2 files changed

+93
-84
lines changed

2 files changed

+93
-84
lines changed

compiler/rustc_middle/src/ty/util.rs

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFolder};
55
use crate::ty::layout::IntegerExt;
66
use crate::ty::query::TyCtxtAt;
77
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
8-
use crate::ty::{
9-
self, DebruijnIndex, DefIdTree, EarlyBinder, List, ReEarlyBound, Ty, TyCtxt, TyKind::*,
10-
TypeFoldable,
11-
};
8+
use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
129
use rustc_apfloat::Float as _;
1310
use rustc_ast as ast;
1411
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@@ -18,6 +15,7 @@ use rustc_errors::ErrorGuaranteed;
1815
use rustc_hir as hir;
1916
use rustc_hir::def::{CtorOf, DefKind, Res};
2017
use rustc_hir::def_id::DefId;
18+
use rustc_index::bit_set::GrowableBitSet;
2119
use rustc_macros::HashStable;
2220
use rustc_span::{sym, DUMMY_SP};
2321
use rustc_target::abi::{Integer, Size, TargetDataLayout};
@@ -32,6 +30,12 @@ pub struct Discr<'tcx> {
3230
pub ty: Ty<'tcx>,
3331
}
3432

33+
#[derive(Copy, Clone, Debug)]
34+
pub enum NotUniqueParam<'tcx> {
35+
DuplicateParam(ty::GenericArg<'tcx>),
36+
NotParam(ty::GenericArg<'tcx>),
37+
}
38+
3539
impl<'tcx> fmt::Display for Discr<'tcx> {
3640
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3741
match *self.ty.kind() {
@@ -49,8 +53,8 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
4953

5054
fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
5155
let (int, signed) = match *ty.kind() {
52-
Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
53-
Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
56+
ty::Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
57+
ty::Uint(uty) => (Integer::from_uint_ty(&tcx, uty), false),
5458
_ => bug!("non integer discriminant"),
5559
};
5660
(int.size(), signed)
@@ -176,7 +180,7 @@ impl<'tcx> TyCtxt<'tcx> {
176180
if let ty::Adt(def, substs) = *ty.kind() {
177181
for field in def.all_fields() {
178182
let field_ty = field.ty(self, substs);
179-
if let Error(_) = field_ty.kind() {
183+
if let ty::Error(_) = field_ty.kind() {
180184
return true;
181185
}
182186
}
@@ -311,7 +315,7 @@ impl<'tcx> TyCtxt<'tcx> {
311315
let (mut a, mut b) = (source, target);
312316
loop {
313317
match (&a.kind(), &b.kind()) {
314-
(&Adt(a_def, a_substs), &Adt(b_def, b_substs))
318+
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
315319
if a_def == b_def && a_def.is_struct() =>
316320
{
317321
if let Some(f) = a_def.non_enum_variant().fields.last() {
@@ -321,7 +325,7 @@ impl<'tcx> TyCtxt<'tcx> {
321325
break;
322326
}
323327
}
324-
(&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => {
328+
(&ty::Tuple(a_tys), &ty::Tuple(b_tys)) if a_tys.len() == b_tys.len() => {
325329
if let Some(&a_last) = a_tys.last() {
326330
a = a_last;
327331
b = *b_tys.last().unwrap();
@@ -427,7 +431,7 @@ impl<'tcx> TyCtxt<'tcx> {
427431
.filter(|&(_, k)| {
428432
match k.unpack() {
429433
GenericArgKind::Lifetime(region) => match region.kind() {
430-
ReEarlyBound(ref ebr) => {
434+
ty::ReEarlyBound(ref ebr) => {
431435
!impl_generics.region_param(ebr, self).pure_wrt_drop
432436
}
433437
// Error: not a region param
@@ -453,6 +457,49 @@ impl<'tcx> TyCtxt<'tcx> {
453457
result
454458
}
455459

460+
/// Checks whether each generic argument is simply a unique generic parameter.
461+
pub fn uses_unique_generic_params(
462+
self,
463+
substs: SubstsRef<'tcx>,
464+
ignore_regions: bool,
465+
) -> Result<(), NotUniqueParam<'tcx>> {
466+
let mut seen = GrowableBitSet::default();
467+
for arg in substs {
468+
match arg.unpack() {
469+
GenericArgKind::Lifetime(lt) => {
470+
if !ignore_regions {
471+
match lt.kind() {
472+
ty::ReEarlyBound(p) => {
473+
if !seen.insert(p.index) {
474+
return Err(NotUniqueParam::DuplicateParam(lt.into()));
475+
}
476+
}
477+
_ => return Err(NotUniqueParam::NotParam(lt.into())),
478+
}
479+
}
480+
}
481+
GenericArgKind::Type(t) => match t.kind() {
482+
ty::Param(p) => {
483+
if !seen.insert(p.index) {
484+
return Err(NotUniqueParam::DuplicateParam(t.into()));
485+
}
486+
}
487+
_ => return Err(NotUniqueParam::NotParam(t.into())),
488+
},
489+
GenericArgKind::Const(c) => match c.val() {
490+
ty::ConstKind::Param(p) => {
491+
if !seen.insert(p.index) {
492+
return Err(NotUniqueParam::DuplicateParam(c.into()));
493+
}
494+
}
495+
_ => return Err(NotUniqueParam::NotParam(c.into())),
496+
},
497+
}
498+
}
499+
500+
Ok(())
501+
}
502+
456503
/// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
457504
/// that closures have a `DefId`, but the closure *expression* also
458505
/// has a `HirId` that is located within the context where the
@@ -594,30 +641,33 @@ impl<'tcx> TyCtxt<'tcx> {
594641
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
595642
}
596643

597-
pub fn bound_type_of(self, def_id: DefId) -> EarlyBinder<Ty<'tcx>> {
598-
EarlyBinder(self.type_of(def_id))
644+
pub fn bound_type_of(self, def_id: DefId) -> ty::EarlyBinder<Ty<'tcx>> {
645+
ty::EarlyBinder(self.type_of(def_id))
599646
}
600647

601-
pub fn bound_fn_sig(self, def_id: DefId) -> EarlyBinder<ty::PolyFnSig<'tcx>> {
602-
EarlyBinder(self.fn_sig(def_id))
648+
pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> {
649+
ty::EarlyBinder(self.fn_sig(def_id))
603650
}
604651

605-
pub fn bound_impl_trait_ref(self, def_id: DefId) -> Option<EarlyBinder<ty::TraitRef<'tcx>>> {
606-
self.impl_trait_ref(def_id).map(|i| EarlyBinder(i))
652+
pub fn bound_impl_trait_ref(
653+
self,
654+
def_id: DefId,
655+
) -> Option<ty::EarlyBinder<ty::TraitRef<'tcx>>> {
656+
self.impl_trait_ref(def_id).map(|i| ty::EarlyBinder(i))
607657
}
608658

609659
pub fn bound_explicit_item_bounds(
610660
self,
611661
def_id: DefId,
612-
) -> EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
613-
EarlyBinder(self.explicit_item_bounds(def_id))
662+
) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
663+
ty::EarlyBinder(self.explicit_item_bounds(def_id))
614664
}
615665

616666
pub fn bound_item_bounds(
617667
self,
618668
def_id: DefId,
619-
) -> EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
620-
EarlyBinder(self.item_bounds(def_id))
669+
) -> ty::EarlyBinder<&'tcx ty::List<ty::Predicate<'tcx>>> {
670+
ty::EarlyBinder(self.item_bounds(def_id))
621671
}
622672
}
623673

@@ -930,35 +980,40 @@ impl<'tcx> Ty<'tcx> {
930980
pub fn is_structural_eq_shallow(self, tcx: TyCtxt<'tcx>) -> bool {
931981
match self.kind() {
932982
// Look for an impl of both `PartialStructuralEq` and `StructuralEq`.
933-
Adt(..) => tcx.has_structural_eq_impls(self),
983+
ty::Adt(..) => tcx.has_structural_eq_impls(self),
934984

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

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

944994
// Raw pointers use bitwise comparison.
945-
RawPtr(_) | FnPtr(_) => true,
995+
ty::RawPtr(_) | ty::FnPtr(_) => true,
946996

947997
// Floating point numbers are not `Eq`.
948-
Float(_) => false,
998+
ty::Float(_) => false,
949999

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

9521002
// Anonymous function types
953-
FnDef(..) | Closure(..) | Dynamic(..) | Generator(..) => false,
1003+
ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Generator(..) => false,
9541004

9551005
// Generic or inferred types
9561006
//
9571007
// FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
9581008
// called for known, fully-monomorphized types.
959-
Projection(_) | Opaque(..) | Param(_) | Bound(..) | Placeholder(_) | Infer(_) => false,
1009+
ty::Projection(_)
1010+
| ty::Opaque(..)
1011+
| ty::Param(_)
1012+
| ty::Bound(..)
1013+
| ty::Placeholder(_)
1014+
| ty::Infer(_) => false,
9601015

961-
Foreign(_) | GeneratorWitness(..) | Error(_) => false,
1016+
ty::Foreign(_) | ty::GeneratorWitness(..) | ty::Error(_) => false,
9621017
}
9631018
}
9641019

@@ -974,13 +1029,13 @@ impl<'tcx> Ty<'tcx> {
9741029
/// - `&'a *const &'b u8 -> *const &'b u8`
9751030
pub fn peel_refs(self) -> Ty<'tcx> {
9761031
let mut ty = self;
977-
while let Ref(_, inner_ty, _) = ty.kind() {
1032+
while let ty::Ref(_, inner_ty, _) = ty.kind() {
9781033
ty = *inner_ty;
9791034
}
9801035
ty
9811036
}
9821037

983-
pub fn outer_exclusive_binder(self) -> DebruijnIndex {
1038+
pub fn outer_exclusive_binder(self) -> ty::DebruijnIndex {
9841039
self.0.outer_exclusive_binder
9851040
}
9861041
}
@@ -1177,8 +1232,8 @@ pub struct AlwaysRequiresDrop;
11771232
/// with their underlying types.
11781233
pub fn normalize_opaque_types<'tcx>(
11791234
tcx: TyCtxt<'tcx>,
1180-
val: &'tcx List<ty::Predicate<'tcx>>,
1181-
) -> &'tcx List<ty::Predicate<'tcx>> {
1235+
val: &'tcx ty::List<ty::Predicate<'tcx>>,
1236+
) -> &'tcx ty::List<ty::Predicate<'tcx>> {
11821237
let mut visitor = OpaqueTypeExpander {
11831238
seen_opaque_tys: FxHashSet::default(),
11841239
expanded_cache: FxHashMap::default(),

compiler/rustc_typeck/src/coherence/orphan.rs

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use rustc_data_structures::fx::FxHashSet;
55
use rustc_errors::struct_span_err;
66
use rustc_errors::ErrorGuaranteed;
77
use rustc_hir as hir;
8-
use rustc_index::bit_set::GrowableBitSet;
98
use rustc_infer::infer::TyCtxtInferExt;
109
use rustc_middle::ty::subst::GenericArgKind;
11-
use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
10+
use rustc_middle::ty::subst::InternalSubsts;
1211
use rustc_middle::ty::{self, ImplPolarity, Ty, TyCtxt, TypeFoldable, TypeVisitor};
1312
use rustc_session::lint;
1413
use rustc_span::def_id::{DefId, LocalDefId};
@@ -325,51 +324,6 @@ fn emit_orphan_check_error<'tcx>(
325324
})
326325
}
327326

328-
#[derive(Default)]
329-
struct AreUniqueParamsVisitor {
330-
seen: GrowableBitSet<u32>,
331-
}
332-
333-
#[derive(Copy, Clone)]
334-
enum NotUniqueParam<'tcx> {
335-
DuplicateParam(GenericArg<'tcx>),
336-
NotParam(GenericArg<'tcx>),
337-
}
338-
339-
impl<'tcx> TypeVisitor<'tcx> for AreUniqueParamsVisitor {
340-
type BreakTy = NotUniqueParam<'tcx>;
341-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
342-
match t.kind() {
343-
ty::Param(p) => {
344-
if self.seen.insert(p.index) {
345-
ControlFlow::CONTINUE
346-
} else {
347-
ControlFlow::Break(NotUniqueParam::DuplicateParam(t.into()))
348-
}
349-
}
350-
_ => ControlFlow::Break(NotUniqueParam::NotParam(t.into())),
351-
}
352-
}
353-
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
354-
// We don't drop candidates during candidate assembly because of region
355-
// constraints, so the behavior for impls only constrained by regions
356-
// will not change.
357-
ControlFlow::CONTINUE
358-
}
359-
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
360-
match c.val() {
361-
ty::ConstKind::Param(p) => {
362-
if self.seen.insert(p.index) {
363-
ControlFlow::CONTINUE
364-
} else {
365-
ControlFlow::Break(NotUniqueParam::DuplicateParam(c.into()))
366-
}
367-
}
368-
_ => ControlFlow::Break(NotUniqueParam::NotParam(c.into())),
369-
}
370-
}
371-
}
372-
373327
/// Lint impls of auto traits if they are likely to have
374328
/// unsound or surprising effects on auto impls.
375329
fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDefId]) {
@@ -400,9 +354,9 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef
400354
// Impls which completely cover a given root type are fine as they
401355
// disable auto impls entirely. So only lint if the substs
402356
// are not a permutation of the identity substs.
403-
match substs.visit_with(&mut AreUniqueParamsVisitor::default()) {
404-
ControlFlow::Continue(()) => {} // ok
405-
ControlFlow::Break(arg) => {
357+
match tcx.uses_unique_generic_params(substs, true) {
358+
Ok(()) => {} // ok
359+
Err(arg) => {
406360
// Ideally:
407361
//
408362
// - compute the requirements for the auto impl candidate
@@ -444,10 +398,10 @@ fn lint_auto_trait_impls(tcx: TyCtxt<'_>, trait_def_id: DefId, impls: &[LocalDef
444398
),
445399
);
446400
match arg {
447-
NotUniqueParam::DuplicateParam(arg) => {
401+
ty::util::NotUniqueParam::DuplicateParam(arg) => {
448402
err.note(&format!("`{}` is mentioned multiple times", arg));
449403
}
450-
NotUniqueParam::NotParam(arg) => {
404+
ty::util::NotUniqueParam::NotParam(arg) => {
451405
err.note(&format!("`{}` is not a generic parameter", arg));
452406
}
453407
}

0 commit comments

Comments
 (0)