Skip to content

Commit

Permalink
Auto merge of #53677 - eddyb:not-my-self, r=<try>
Browse files Browse the repository at this point in the history
rustc: remove Ty::{is_self, has_self_ty}.

Fixes #50125 by replacing special-casing of `Self` (and the gensym hack) with getting the type for the `Self` parameter from the trait, and comparing types with that, instead.

**NOTE**: this is part of #53661, split out to independently check performance impact.
  • Loading branch information
bors committed Aug 24, 2018
2 parents 61b0072 + d110803 commit 9a46196
Show file tree
Hide file tree
Showing 32 changed files with 82 additions and 112 deletions.
32 changes: 14 additions & 18 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1117,19 +1117,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let table = table.borrow();
table.local_id_root.and_then(|did| {
let generics = self.tcx.generics_of(did);
// Account for the case where `did` corresponds to `Self`, which doesn't have
// the expected type argument.
if !param.is_self() {
let type_param = generics.type_param(param, self.tcx);
let hir = &self.tcx.hir;
hir.as_local_node_id(type_param.def_id).map(|id| {
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let mut has_bounds = false;
if let hir_map::NodeGenericParam(ref param) = hir.get(id) {
has_bounds = !param.bounds.is_empty();
}
let type_param = generics.type_param(param, self.tcx);
let hir = &self.tcx.hir;
hir.as_local_node_id(type_param.def_id).and_then(|id| {
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
// Also, `Self` isn't in the HIR so we rule it out here.
if let hir_map::NodeGenericParam(ref hir_param) = hir.get(id) {
let has_bounds = !hir_param.bounds.is_empty();
let sp = hir.span(id);
// `sp` only covers `T`, change it so that it covers
// `T:` when appropriate
Expand All @@ -1141,11 +1137,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
} else {
sp
};
(sp, has_bounds)
})
} else {
None
}
Some((sp, has_bounds))
} else {
None
}
})
})
}
_ => None,
Expand Down
13 changes: 9 additions & 4 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
trait_def_id: DefId,
supertraits_only: bool) -> bool
{
let trait_self_ty = self.mk_self_type();
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
let predicates = if supertraits_only {
self.super_predicates_of(trait_def_id)
Expand All @@ -183,7 +184,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
match predicate {
ty::Predicate::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type.
data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
data.skip_binder().input_types().skip(1).any(|t| {
t.walk().any(|ty| ty == trait_self_ty)
})
}
ty::Predicate::Projection(..) |
ty::Predicate::WellFormed(..) |
Expand All @@ -204,6 +207,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

fn generics_require_sized_self(self, def_id: DefId) -> bool {
let trait_self_ty = self.mk_self_type();
let sized_def_id = match self.lang_items().sized_trait() {
Some(def_id) => def_id,
None => { return false; /* No Sized trait, can't require it! */ }
Expand All @@ -216,7 +220,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
.any(|predicate| {
match predicate {
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
trait_pred.skip_binder().self_ty().is_self()
trait_pred.skip_binder().self_ty() == trait_self_ty
}
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
Expand Down Expand Up @@ -367,12 +371,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// object type, and we cannot resolve `Self as SomeOtherTrait`
// without knowing what `Self` is.

let trait_self_ty = self.mk_self_type();
let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
let mut error = false;
ty.maybe_walk(|ty| {
match ty.sty {
ty::Param(ref param_ty) => {
if param_ty.is_self() {
ty::Param(_) => {
if ty == trait_self_ty {
error = true;
}

Expand Down
8 changes: 1 addition & 7 deletions src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
ty::Projection(_) => "associated type".to_string(),
ty::Param(ref p) => {
if p.is_self() {
"Self".to_string()
} else {
"type parameter".to_string()
}
}
ty::Param(_) => format!("`{}` parameter", self),
ty::Anon(..) => "anonymized type".to_string(),
ty::Error => "type error".to_string(),
}
Expand Down
8 changes: 2 additions & 6 deletions src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,9 @@ impl FlagComputation {
self.add_flags(TypeFlags::HAS_TY_ERR)
}

&ty::Param(ref p) => {
&ty::Param(_) => {
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
if p.is_self() {
self.add_flags(TypeFlags::HAS_SELF);
} else {
self.add_flags(TypeFlags::HAS_PARAMS);
}
self.add_flags(TypeFlags::HAS_PARAMS);
}

&ty::Generator(_, ref substs, _) => {
Expand Down
3 changes: 0 additions & 3 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
fn has_param_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PARAMS)
}
fn has_self_ty(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_SELF)
}
fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1130,7 +1130,6 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
if
!self.tcx.sess.opts.debugging_opts.print_type_sizes ||
layout.ty.has_param_types() ||
layout.ty.has_self_ty() ||
!self.param_env.caller_bounds.is_empty()
{
return;
Expand Down Expand Up @@ -1300,7 +1299,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
let tail = tcx.struct_tail(pointee);
match tail.sty {
ty::Param(_) | ty::Projection(_) => {
debug_assert!(tail.has_param_types() || tail.has_self_ty());
debug_assert!(tail.has_param_types());
Ok(SizeSkeleton::Pointer {
non_zero,
tail: tcx.erase_regions(&tail)
Expand Down
30 changes: 13 additions & 17 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,57 +423,54 @@ pub struct CReaderCacheKey {
bitflags! {
pub struct TypeFlags: u32 {
const HAS_PARAMS = 1 << 0;
const HAS_SELF = 1 << 1;
const HAS_TY_INFER = 1 << 2;
const HAS_RE_INFER = 1 << 3;
const HAS_RE_SKOL = 1 << 4;
const HAS_TY_INFER = 1 << 1;
const HAS_RE_INFER = 1 << 2;
const HAS_RE_SKOL = 1 << 3;

/// Does this have any `ReEarlyBound` regions? Used to
/// determine whether substitition is required, since those
/// represent regions that are bound in a `ty::Generics` and
/// hence may be substituted.
const HAS_RE_EARLY_BOUND = 1 << 5;
const HAS_RE_EARLY_BOUND = 1 << 4;

/// Does this have any region that "appears free" in the type?
/// Basically anything but `ReLateBound` and `ReErased`.
const HAS_FREE_REGIONS = 1 << 6;
const HAS_FREE_REGIONS = 1 << 5;

/// Is an error type reachable?
const HAS_TY_ERR = 1 << 7;
const HAS_PROJECTION = 1 << 8;
const HAS_TY_ERR = 1 << 6;
const HAS_PROJECTION = 1 << 7;

// FIXME: Rename this to the actual property since it's used for generators too
const HAS_TY_CLOSURE = 1 << 9;
const HAS_TY_CLOSURE = 1 << 8;

// true if there are "names" of types and regions and so forth
// that are local to a particular fn
const HAS_FREE_LOCAL_NAMES = 1 << 10;
const HAS_FREE_LOCAL_NAMES = 1 << 9;

// Present if the type belongs in a local type context.
// Only set for Infer other than Fresh.
const KEEP_IN_LOCAL_TCX = 1 << 11;
const KEEP_IN_LOCAL_TCX = 1 << 10;

// Is there a projection that does not involve a bound region?
// Currently we can't normalize projections w/ bound regions.
const HAS_NORMALIZABLE_PROJECTION = 1 << 12;
const HAS_NORMALIZABLE_PROJECTION = 1 << 11;

// Set if this includes a "canonical" type or region var --
// ought to be true only for the results of canonicalization.
const HAS_CANONICAL_VARS = 1 << 13;
const HAS_CANONICAL_VARS = 1 << 12;

/// Does this have any `ReLateBound` regions? Used to check
/// if a global bound is safe to evaluate.
const HAS_RE_LATE_BOUND = 1 << 14;
const HAS_RE_LATE_BOUND = 1 << 13;

const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits;

// Flags representing the nominal content of a type,
// computed by FlagsComputation. If you add a new nominal
// flag, it should be added here too.
const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_TY_INFER.bits |
TypeFlags::HAS_RE_INFER.bits |
TypeFlags::HAS_RE_SKOL.bits |
Expand Down Expand Up @@ -1632,7 +1629,6 @@ impl<'tcx> ParamEnv<'tcx> {
if value.has_skol()
|| value.needs_infer()
|| value.has_param_types()
|| value.has_self_ty()
{
ParamEnvAnd {
param_env: self,
Expand Down
18 changes: 0 additions & 18 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,17 +982,6 @@ impl<'a, 'gcx, 'tcx> ParamTy {
pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
tcx.mk_ty_param(self.idx, self.name)
}

pub fn is_self(&self) -> bool {
// FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere,
// but this should only be possible when using `-Z continue-parse-after-error` like
// `compile-fail/issue-36638.rs`.
if self.name == keywords::SelfType.name().as_str() && self.idx == 0 {
true
} else {
false
}
}
}

/// A [De Bruijn index][dbi] is a standard means of representing
Expand Down Expand Up @@ -1519,13 +1508,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}

pub fn is_self(&self) -> bool {
match self.sty {
Param(ref p) => p.is_self(),
_ => false,
}
}

pub fn is_slice(&self) -> bool {
match self.sty {
RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
// A trait method, from any number of possible sources.
// Attempt to select a concrete impl before checking.
ty::TraitContainer(trait_def_id) => {
let trait_self_ty = tcx.mk_self_type();
let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs);
let trait_ref = ty::Binder::bind(trait_ref);
let span = tcx.hir.span(expr_id);
Expand All @@ -1090,7 +1091,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
// If `T` is `Self`, then this call is inside
// a default method definition.
Ok(Some(traits::VtableParam(_))) => {
let on_self = trait_ref.self_ty().is_self();
let on_self = trait_ref.self_ty() == trait_self_ty;
// We can only be recurring in a default
// method if we're being called literally
// on the `Self` type.
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
let default_needs_object_self = |param: &ty::GenericParamDef| {
if let GenericParamDefKind::Type { has_default, .. } = param.kind {
if is_object && has_default {
if tcx.at(span).type_of(param.def_id).has_self_ty() {
let trait_self_ty = tcx.mk_self_type();
let default = tcx.at(span).type_of(param.def_id);
if default.walk().any(|ty| ty == trait_self_ty) {
// There is no suitable inference default for a type parameter
// that references self, in an object type.
return true;
Expand Down
4 changes: 0 additions & 4 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,10 +919,6 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut i = 0;
params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Type { ref default, synthetic, .. } => {
if param.name.ident().name == keywords::SelfType.name() {
span_bug!(param.span, "`Self` should not be the name of a regular parameter");
}

if !allow_defaults && default.is_some() {
if !tcx.features().default_type_parameter_fallback {
tcx.lint_node(
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_typeck/outlives/implicit_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ pub fn check_explicit_predicates<'tcx>(
debug!("required_predicates = {:?}", required_predicates);
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id);

let ignore_self_ty = if ignore_self_ty {
Some(tcx.mk_self_type())
} else {
None
};
for outlives_predicate in explicit_predicates.iter() {
debug!("outlives_predicate = {:?}", &outlives_predicate);

Expand Down Expand Up @@ -297,7 +302,7 @@ pub fn check_explicit_predicates<'tcx>(
// to apply the substs, and not filter this predicate, we might then falsely
// conclude that e.g. `X: 'x` was a reasonable inferred requirement.
if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() {
if ty.is_self() && ignore_self_ty {
if Some(ty) == ignore_self_ty {
debug!("skipping self ty = {:?}", &ty);
continue;
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/clean/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,11 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId,
if child == trait_ {
return true
}
let trait_self_ty = cx.tcx.mk_self_type();
let predicates = cx.tcx.super_predicates_of(child).predicates;
predicates.iter().filter_map(|pred| {
if let ty::Predicate::Trait(ref pred) = *pred {
if pred.skip_binder().trait_ref.self_ty().is_self() {
if pred.skip_binder().trait_ref.self_ty() == trait_self_ty {
Some(pred.def_id())
} else {
None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<Adapter<I> as Iterator>::Item == std::op
--> $DIR/associated-types-issue-20346.rs:44:5
|
LL | is_iterator_of::<Option<T>, _>(&adapter); //~ ERROR type mismatch
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found enum `std::option::Option`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T` parameter, found enum `std::option::Option`
|
= note: expected type `T`
found type `std::option::Option<T>`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/compare-method/reordered-type-param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | fn b<C:Clone,D>(&self, x: C) -> C;
| - type in trait
...
LL | fn b<F:Clone,G>(&self, _x: G) -> G { panic!() } //~ ERROR method `b` has an incompatible type
| ^ expected type parameter, found a different type parameter
| ^ expected `F` parameter, found `G` parameter
|
= note: expected type `fn(&E, F) -> F`
found type `fn(&E, G) -> G`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | fn foo<A: Debug>(&self, a: &A, b: &impl Debug);
| -- type in trait
...
LL | fn foo<B: Debug>(&self, a: &impl Debug, b: &B) { }
| ^^^^^^^^^^^ expected type parameter, found a different type parameter
| ^^^^^^^^^^^ expected `B` parameter, found `impl Debug` parameter
|
= note: expected type `fn(&(), &B, &impl Debug)`
found type `fn(&(), &impl Debug, &B)`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/impl-trait/universal-mismatched-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | fn foo(x: impl Debug) -> String {
| ------ expected `std::string::String` because of return type
LL | x //~ ERROR mismatched types
| ^ expected struct `std::string::String`, found type parameter
| ^ expected struct `std::string::String`, found `impl Debug` parameter
|
= note: expected type `std::string::String`
found type `impl Debug`
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/impl-trait/universal-two-impl-traits.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ error[E0308]: mismatched types
--> $DIR/universal-two-impl-traits.rs:15:9
|
LL | a = y; //~ ERROR mismatched
| ^ expected type parameter, found a different type parameter
| ^ expected `impl Debug` parameter, found a different `impl Debug` parameter
|
= note: expected type `impl Debug` (type parameter)
found type `impl Debug` (type parameter)
= note: expected type `impl Debug` (`impl Debug` parameter)
found type `impl Debug` (`impl Debug` parameter)

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-13853.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | fn nodes<'a, I: Iterator<Item=&'a N>>(&self) -> I
| - expected `I` because of return type
...
LL | self.iter() //~ ERROR mismatched types
| ^^^^^^^^^^^ expected type parameter, found struct `std::slice::Iter`
| ^^^^^^^^^^^ expected `I` parameter, found struct `std::slice::Iter`
|
= note: expected type `I`
found type `std::slice::Iter<'_, N>`
Expand Down
Loading

0 comments on commit 9a46196

Please sign in to comment.