Skip to content

Commit a807902

Browse files
committed
Auto merge of rust-lang#63463 - matthewjasper:ty_param_cleanup, r=petrochenkov
Don't special case the `Self` parameter by name This results in a couple of small diagnostic regressions. They could be avoided by keeping the special case just for diagnostics, but that seems worse. closes rust-lang#50125 cc rust-lang#60869
2 parents 0ccbae2 + 24587d2 commit a807902

24 files changed

+124
-183
lines changed

src/librustc/hir/lowering.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -2524,15 +2524,6 @@ impl<'a> LoweringContext<'a> {
25242524
(param_name, kind)
25252525
}
25262526
GenericParamKind::Type { ref default, .. } => {
2527-
// Don't expose `Self` (recovered "keyword used as ident" parse error).
2528-
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
2529-
// Instead, use `gensym("Self")` to create a distinct name that looks the same.
2530-
let ident = if param.ident.name == kw::SelfUpper {
2531-
param.ident.gensym()
2532-
} else {
2533-
param.ident
2534-
};
2535-
25362527
let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
25372528
if !add_bounds.is_empty() {
25382529
let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter();
@@ -2551,7 +2542,7 @@ impl<'a> LoweringContext<'a> {
25512542
.next(),
25522543
};
25532544

2554-
(hir::ParamName::Plain(ident), kind)
2545+
(hir::ParamName::Plain(param.ident), kind)
25552546
}
25562547
GenericParamKind::Const { ref ty } => {
25572548
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const {

src/librustc/infer/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1329,15 +1329,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13291329
let generics = self.tcx.generics_of(did);
13301330
// Account for the case where `did` corresponds to `Self`, which doesn't have
13311331
// the expected type argument.
1332-
if !param.is_self() {
1332+
if !(generics.has_self && param.index == 0) {
13331333
let type_param = generics.type_param(param, self.tcx);
13341334
let hir = &self.tcx.hir();
13351335
hir.as_local_hir_id(type_param.def_id).map(|id| {
13361336
// Get the `hir::Param` to verify whether it already has any bounds.
13371337
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
13381338
// instead we suggest `T: 'a + 'b` in that case.
13391339
let mut has_bounds = false;
1340-
if let Node::GenericParam(ref param) = hir.get(id) {
1340+
if let Node::GenericParam(param) = hir.get(id) {
13411341
has_bounds = !param.bounds.is_empty();
13421342
}
13431343
let sp = hir.span(id);

src/librustc/traits/object_safety.rs

+57-52
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl<'tcx> TyCtxt<'tcx> {
9191
pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
9292
-> Vec<ObjectSafetyViolation>
9393
{
94+
debug_assert!(self.generics_of(trait_def_id).has_self);
9495
let violations = traits::supertrait_def_ids(self, trait_def_id)
9596
.filter(|&def_id| self.predicates_reference_self(def_id, true))
9697
.map(|_| ObjectSafetyViolation::SupertraitSelf)
@@ -106,16 +107,33 @@ impl<'tcx> TyCtxt<'tcx> {
106107
pub fn object_safety_violations(self, trait_def_id: DefId)
107108
-> Vec<ObjectSafetyViolation>
108109
{
110+
debug_assert!(self.generics_of(trait_def_id).has_self);
109111
debug!("object_safety_violations: {:?}", trait_def_id);
110112

111113
traits::supertrait_def_ids(self, trait_def_id)
112114
.flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
113115
.collect()
114116
}
115117

116-
fn object_safety_violations_for_trait(self, trait_def_id: DefId)
117-
-> Vec<ObjectSafetyViolation>
118-
{
118+
/// We say a method is *vtable safe* if it can be invoked on a trait
119+
/// object. Note that object-safe traits can have some
120+
/// non-vtable-safe methods, so long as they require `Self:Sized` or
121+
/// otherwise ensure that they cannot be used when `Self=Trait`.
122+
pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool {
123+
debug_assert!(self.generics_of(trait_def_id).has_self);
124+
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
125+
// Any method that has a `Self : Sized` requisite can't be called.
126+
if self.generics_require_sized_self(method.def_id) {
127+
return false;
128+
}
129+
130+
match self.virtual_call_violation_for_method(trait_def_id, method) {
131+
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
132+
Some(_) => false,
133+
}
134+
}
135+
136+
fn object_safety_violations_for_trait(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> {
119137
// Check methods for violations.
120138
let mut violations: Vec<_> = self.associated_items(trait_def_id)
121139
.filter(|item| item.kind == ty::AssocKind::Method)
@@ -163,14 +181,16 @@ impl<'tcx> TyCtxt<'tcx> {
163181
fn predicates_reference_self(
164182
self,
165183
trait_def_id: DefId,
166-
supertraits_only: bool) -> bool
167-
{
184+
supertraits_only: bool,
185+
) -> bool {
168186
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
169187
let predicates = if supertraits_only {
170188
self.super_predicates_of(trait_def_id)
171189
} else {
172190
self.predicates_of(trait_def_id)
173191
};
192+
let self_ty = self.types.self_param;
193+
let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty);
174194
predicates
175195
.predicates
176196
.iter()
@@ -179,7 +199,7 @@ impl<'tcx> TyCtxt<'tcx> {
179199
match predicate {
180200
ty::Predicate::Trait(ref data) => {
181201
// In the case of a trait predicate, we can skip the "self" type.
182-
data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
202+
data.skip_binder().input_types().skip(1).any(has_self_ty)
183203
}
184204
ty::Predicate::Projection(ref data) => {
185205
// And similarly for projections. This should be redundant with
@@ -199,7 +219,7 @@ impl<'tcx> TyCtxt<'tcx> {
199219
.trait_ref(self)
200220
.input_types()
201221
.skip(1)
202-
.any(|t| t.has_self_ty())
222+
.any(has_self_ty)
203223
}
204224
ty::Predicate::WellFormed(..) |
205225
ty::Predicate::ObjectSafe(..) |
@@ -229,11 +249,11 @@ impl<'tcx> TyCtxt<'tcx> {
229249
let predicates = predicates.instantiate_identity(self).predicates;
230250
elaborate_predicates(self, predicates)
231251
.any(|predicate| match predicate {
232-
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
233-
trait_pred.skip_binder().self_ty().is_self()
252+
ty::Predicate::Trait(ref trait_pred) => {
253+
trait_pred.def_id() == sized_def_id
254+
&& trait_pred.skip_binder().self_ty().is_param(0)
234255
}
235256
ty::Predicate::Projection(..) |
236-
ty::Predicate::Trait(..) |
237257
ty::Predicate::Subtype(..) |
238258
ty::Predicate::RegionOutlives(..) |
239259
ty::Predicate::WellFormed(..) |
@@ -248,11 +268,11 @@ impl<'tcx> TyCtxt<'tcx> {
248268
}
249269

250270
/// Returns `Some(_)` if this method makes the containing trait not object safe.
251-
fn object_safety_violation_for_method(self,
252-
trait_def_id: DefId,
253-
method: &ty::AssocItem)
254-
-> Option<MethodViolationCode>
255-
{
271+
fn object_safety_violation_for_method(
272+
self,
273+
trait_def_id: DefId,
274+
method: &ty::AssocItem,
275+
) -> Option<MethodViolationCode> {
256276
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
257277
// Any method that has a `Self : Sized` requisite is otherwise
258278
// exempt from the regulations.
@@ -263,36 +283,15 @@ impl<'tcx> TyCtxt<'tcx> {
263283
self.virtual_call_violation_for_method(trait_def_id, method)
264284
}
265285

266-
/// We say a method is *vtable safe* if it can be invoked on a trait
267-
/// object. Note that object-safe traits can have some
268-
/// non-vtable-safe methods, so long as they require `Self:Sized` or
269-
/// otherwise ensure that they cannot be used when `Self=Trait`.
270-
pub fn is_vtable_safe_method(self,
271-
trait_def_id: DefId,
272-
method: &ty::AssocItem)
273-
-> bool
274-
{
275-
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
276-
// Any method that has a `Self : Sized` requisite can't be called.
277-
if self.generics_require_sized_self(method.def_id) {
278-
return false;
279-
}
280-
281-
match self.virtual_call_violation_for_method(trait_def_id, method) {
282-
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
283-
Some(_) => false,
284-
}
285-
}
286-
287286
/// Returns `Some(_)` if this method cannot be called on a trait
288287
/// object; this does not necessarily imply that the enclosing trait
289288
/// is not object safe, because the method might have a where clause
290289
/// `Self:Sized`.
291-
fn virtual_call_violation_for_method(self,
292-
trait_def_id: DefId,
293-
method: &ty::AssocItem)
294-
-> Option<MethodViolationCode>
295-
{
290+
fn virtual_call_violation_for_method(
291+
self,
292+
trait_def_id: DefId,
293+
method: &ty::AssocItem,
294+
) -> Option<MethodViolationCode> {
296295
// The method's first parameter must be named `self`
297296
if !method.method_has_self_argument {
298297
return Some(MethodViolationCode::StaticMethod);
@@ -323,7 +322,9 @@ impl<'tcx> TyCtxt<'tcx> {
323322
.collect::<Vec<_>>()
324323
// Do a shallow visit so that `contains_illegal_self_type_reference`
325324
// may apply it's custom visiting.
326-
.visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t)) {
325+
.visit_tys_shallow(|t| {
326+
self.contains_illegal_self_type_reference(trait_def_id, t)
327+
}) {
327328
let span = self.def_span(method.def_id);
328329
return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
329330
}
@@ -337,7 +338,7 @@ impl<'tcx> TyCtxt<'tcx> {
337338
// However, this is already considered object-safe. We allow it as a special case here.
338339
// FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
339340
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`
340-
if receiver_ty != self.mk_self_type() {
341+
if receiver_ty != self.types.self_param {
341342
if !self.receiver_is_dispatchable(method, receiver_ty) {
342343
return Some(MethodViolationCode::UndispatchableReceiver);
343344
} else {
@@ -404,7 +405,10 @@ impl<'tcx> TyCtxt<'tcx> {
404405
/// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
405406
/// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`.
406407
fn receiver_for_self_ty(
407-
self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
408+
self,
409+
receiver_ty: Ty<'tcx>,
410+
self_ty: Ty<'tcx>,
411+
method_def_id: DefId,
408412
) -> Ty<'tcx> {
409413
debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
410414
let substs = InternalSubsts::for_item(self, method_def_id, |param, _| {
@@ -555,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> {
555559
// Self: Unsize<U>
556560
let unsize_predicate = ty::TraitRef {
557561
def_id: unsize_did,
558-
substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
562+
substs: self.mk_substs_trait(self.types.self_param, &[unsized_self_ty.into()]),
559563
}.to_predicate();
560564

561565
// U: Trait<Arg1, ..., ArgN>
@@ -608,11 +612,11 @@ impl<'tcx> TyCtxt<'tcx> {
608612
})
609613
}
610614

611-
fn contains_illegal_self_type_reference(self,
612-
trait_def_id: DefId,
613-
ty: Ty<'tcx>)
614-
-> bool
615-
{
615+
fn contains_illegal_self_type_reference(
616+
self,
617+
trait_def_id: DefId,
618+
ty: Ty<'tcx>,
619+
) -> bool {
616620
// This is somewhat subtle. In general, we want to forbid
617621
// references to `Self` in the argument and return types,
618622
// since the value of `Self` is erased. However, there is one
@@ -654,10 +658,11 @@ impl<'tcx> TyCtxt<'tcx> {
654658

655659
let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
656660
let mut error = false;
661+
let self_ty = self.types.self_param;
657662
ty.maybe_walk(|ty| {
658663
match ty.sty {
659-
ty::Param(ref param_ty) => {
660-
if param_ty.is_self() {
664+
ty::Param(_) => {
665+
if ty == self_ty {
661666
error = true;
662667
}
663668

src/librustc/ty/context.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ pub struct CommonTypes<'tcx> {
173173
pub f32: Ty<'tcx>,
174174
pub f64: Ty<'tcx>,
175175
pub never: Ty<'tcx>,
176+
pub self_param: Ty<'tcx>,
176177
pub err: Ty<'tcx>,
177178

178179
/// Dummy type used for the `Self` of a `TraitRef` created for converting
@@ -915,6 +916,10 @@ impl<'tcx> CommonTypes<'tcx> {
915916
u128: mk(Uint(ast::UintTy::U128)),
916917
f32: mk(Float(ast::FloatTy::F32)),
917918
f64: mk(Float(ast::FloatTy::F64)),
919+
self_param: mk(ty::Param(ty::ParamTy {
920+
index: 0,
921+
name: kw::SelfUpper.as_interned_str(),
922+
})),
918923

919924
trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
920925
}
@@ -2566,10 +2571,6 @@ impl<'tcx> TyCtxt<'tcx> {
25662571
})
25672572
}
25682573

2569-
#[inline]
2570-
pub fn mk_self_type(self) -> Ty<'tcx> {
2571-
self.mk_ty_param(0, kw::SelfUpper.as_interned_str())
2572-
}
25732574

25742575
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> {
25752576
match param.kind {

src/librustc/ty/error.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,7 @@ impl<'tcx> ty::TyS<'tcx> {
239239
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
240240
ty::Projection(_) => "associated type".into(),
241241
ty::UnnormalizedProjection(_) => "non-normalized associated type".into(),
242-
ty::Param(ref p) => {
243-
if p.is_self() {
244-
"Self".into()
245-
} else {
246-
"type parameter".into()
247-
}
248-
}
242+
ty::Param(_) => "type parameter".into(),
249243
ty::Opaque(..) => "opaque type".into(),
250244
ty::Error => "type error".into(),
251245
}

src/librustc/ty/flags.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::ty::subst::{SubstsRef, UnpackedKind};
2-
use crate::ty::{self, Ty, TypeFlags, TypeFoldable, InferConst};
2+
use crate::ty::{self, Ty, TypeFlags, InferConst};
33
use crate::mir::interpret::ConstValue;
44

55
#[derive(Debug)]
@@ -86,13 +86,9 @@ impl FlagComputation {
8686
self.add_flags(TypeFlags::HAS_TY_ERR)
8787
}
8888

89-
&ty::Param(ref p) => {
89+
&ty::Param(_) => {
9090
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
91-
if p.is_self() {
92-
self.add_flags(TypeFlags::HAS_SELF);
93-
} else {
94-
self.add_flags(TypeFlags::HAS_PARAMS);
95-
}
91+
self.add_flags(TypeFlags::HAS_PARAMS);
9692
}
9793

9894
&ty::Generator(_, ref substs, _) => {
@@ -143,11 +139,6 @@ impl FlagComputation {
143139
}
144140

145141
&ty::Projection(ref data) => {
146-
// currently we can't normalize projections that
147-
// include bound regions, so track those separately.
148-
if !data.has_escaping_bound_vars() {
149-
self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
150-
}
151142
self.add_flags(TypeFlags::HAS_PROJECTION);
152143
self.add_projection_ty(data);
153144
}
@@ -243,7 +234,7 @@ impl FlagComputation {
243234
match c.val {
244235
ConstValue::Unevaluated(_, substs) => {
245236
self.add_substs(substs);
246-
self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION);
237+
self.add_flags(TypeFlags::HAS_PROJECTION);
247238
},
248239
ConstValue::Infer(infer) => {
249240
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);

src/librustc/ty/fold.rs

-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
8585
fn has_param_types(&self) -> bool {
8686
self.has_type_flags(TypeFlags::HAS_PARAMS)
8787
}
88-
fn has_self_ty(&self) -> bool {
89-
self.has_type_flags(TypeFlags::HAS_SELF)
90-
}
9188
fn has_infer_types(&self) -> bool {
9289
self.has_type_flags(TypeFlags::HAS_TY_INFER)
9390
}

src/librustc/ty/instance.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,9 @@ impl<'tcx> Instance<'tcx> {
298298
) -> Option<Instance<'tcx>> {
299299
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
300300
let fn_sig = tcx.fn_sig(def_id);
301-
let is_vtable_shim =
302-
fn_sig.inputs().skip_binder().len() > 0 && fn_sig.input(0).skip_binder().is_self();
301+
let is_vtable_shim = fn_sig.inputs().skip_binder().len() > 0
302+
&& fn_sig.input(0).skip_binder().is_param(0)
303+
&& tcx.generics_of(def_id).has_self;
303304
if is_vtable_shim {
304305
debug!(" => associated item with unsizeable self: Self");
305306
Some(Instance {

src/librustc/ty/layout.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
16011601
// resulting from the final codegen session.
16021602
if
16031603
layout.ty.has_param_types() ||
1604-
layout.ty.has_self_ty() ||
16051604
!self.param_env.caller_bounds.is_empty()
16061605
{
16071606
return;
@@ -1767,7 +1766,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
17671766
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
17681767
match tail.sty {
17691768
ty::Param(_) | ty::Projection(_) => {
1770-
debug_assert!(tail.has_param_types() || tail.has_self_ty());
1769+
debug_assert!(tail.has_param_types());
17711770
Ok(SizeSkeleton::Pointer {
17721771
non_zero,
17731772
tail: tcx.erase_regions(&tail)

0 commit comments

Comments
 (0)