object_safety.rs 27.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! "Object safety" refers to the ability for a trait to be converted
//! to an object. In general, traits may only be converted to an
//! object if all of their methods meet certain criteria. In particular,
//! they must:
//!
16 17
//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
//!     that doesn't contain the vtable;
18 19 20 21 22
//!   - not reference the erased type `Self` except for in this receiver;
//!   - not have generic type parameters

use super::elaborate_predicates;

23
use hir::def_id::DefId;
24
use lint;
25 26 27
use traits::{self, Obligation, ObligationCause};
use ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate};
use ty::subst::{Subst, Substs};
28
use std::borrow::Cow;
29 30
use std::iter::{self};
use syntax::ast::{self, Name};
31
use syntax_pos::Span;
32

33
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
34
pub enum ObjectSafetyViolation {
35 36 37
    /// Self : Sized declared on the trait
    SizedSelf,

38 39 40 41
    /// Supertrait reference references `Self` an in illegal location
    /// (e.g. `trait Foo : Bar<Self>`)
    SupertraitSelf,

J
Joseph Crail 已提交
42
    /// Method has something illegal
43
    Method(ast::Name, MethodViolationCode),
44 45 46

    /// Associated const
    AssociatedConst(ast::Name),
47 48
}

49 50 51 52 53 54 55
impl ObjectSafetyViolation {
    pub fn error_msg(&self) -> Cow<'static, str> {
        match *self {
            ObjectSafetyViolation::SizedSelf =>
                "the trait cannot require that `Self : Sized`".into(),
            ObjectSafetyViolation::SupertraitSelf =>
                "the trait cannot use `Self` as a type parameter \
56
                 in the supertraits or where-clauses".into(),
57 58 59 60 61
            ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
                format!("method `{}` has no receiver", name).into(),
            ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
                format!("method `{}` references the `Self` type \
                         in its arguments or return type", name).into(),
62 63 64
            ObjectSafetyViolation::Method(name,
                                            MethodViolationCode::WhereClauseReferencesSelf(_)) =>
                format!("method `{}` references the `Self` type in where clauses", name).into(),
65 66
            ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
                format!("method `{}` has generic type parameters", name).into(),
67 68
            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
                format!("method `{}`'s receiver cannot be dispatched on", name).into(),
69
            ObjectSafetyViolation::AssociatedConst(name) =>
W
Without Boats 已提交
70
                format!("the trait cannot contain associated consts like `{}`", name).into(),
71 72 73 74
        }
    }
}

75
/// Reasons a method might not be object-safe.
76
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
77
pub enum MethodViolationCode {
N
Niko Matsakis 已提交
78
    /// e.g., `fn foo()`
79 80
    StaticMethod,

N
Niko Matsakis 已提交
81
    /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self`
82 83
    ReferencesSelf,

84 85 86
    /// e.g. `fn foo(&self) where Self: Clone`
    WhereClauseReferencesSelf(Span),

N
Niko Matsakis 已提交
87
    /// e.g., `fn foo<A>()`
88
    Generic,
89

90 91
    /// the method's receiver (`self` argument) can't be dispatched on
    UndispatchableReceiver,
92 93
}

94
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
95

96 97 98 99 100
    /// Returns the object safety violations that affect
    /// astconv - currently, Self in supertraits. This is needed
    /// because `object_safety_violations` can't be used during
    /// type collection.
    pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
101
                                            -> Vec<ObjectSafetyViolation>
102
    {
103 104 105 106
        let violations = traits::supertrait_def_ids(self, trait_def_id)
            .filter(|&def_id| self.predicates_reference_self(def_id, true))
            .map(|_| ObjectSafetyViolation::SupertraitSelf)
            .collect();
107

108 109 110
        debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}",
               trait_def_id,
               violations);
111

112 113 114 115
        violations
    }

    pub fn object_safety_violations(self, trait_def_id: DefId)
116
                                    -> Vec<ObjectSafetyViolation>
117
    {
118 119
        debug!("object_safety_violations: {:?}", trait_def_id);

120 121 122 123
        traits::supertrait_def_ids(self, trait_def_id)
            .flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
            .collect()
    }
124

125
    fn object_safety_violations_for_trait(self, trait_def_id: DefId)
126
                                          -> Vec<ObjectSafetyViolation>
127 128
    {
        // Check methods for violations.
129 130
        let mut violations: Vec<_> = self.associated_items(trait_def_id)
            .filter(|item| item.kind == ty::AssociatedKind::Method)
131
            .filter_map(|item|
132
                self.object_safety_violation_for_method(trait_def_id, &item)
133
                    .map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
134
            ).filter(|violation| {
135
                if let ObjectSafetyViolation::Method(_,
136 137 138
                    MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
                {
                    // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
139 140 141 142 143 144
                    // It's also hard to get a use site span, so we use the method definition span.
                    self.lint_node_note(
                        lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
                        ast::CRATE_NODE_ID,
                        *span,
                        &format!("the trait `{}` cannot be made into an object",
145
                                 self.item_path_str(trait_def_id)),
146 147 148 149 150
                        &violation.error_msg());
                    false
                } else {
                    true
                }
151
            }).collect();
152

153 154 155 156
        // Check the trait itself.
        if self.trait_has_sized_self(trait_def_id) {
            violations.push(ObjectSafetyViolation::SizedSelf);
        }
157
        if self.predicates_reference_self(trait_def_id, false) {
158 159
            violations.push(ObjectSafetyViolation::SupertraitSelf);
        }
160

161 162
        violations.extend(self.associated_items(trait_def_id)
            .filter(|item| item.kind == ty::AssociatedKind::Const)
163
            .map(|item| ObjectSafetyViolation::AssociatedConst(item.ident.name)));
164

165 166 167
        debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
               trait_def_id,
               violations);
168

169 170
        violations
    }
171

172 173 174 175 176
    fn predicates_reference_self(
        self,
        trait_def_id: DefId,
        supertraits_only: bool) -> bool
    {
177
        let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
178
        let predicates = if supertraits_only {
179
            self.super_predicates_of(trait_def_id)
180
        } else {
181
            self.predicates_of(trait_def_id)
182
        };
183 184 185
        predicates
            .predicates
            .into_iter()
186
            .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref))
187 188 189 190
            .any(|predicate| {
                match predicate {
                    ty::Predicate::Trait(ref data) => {
                        // In the case of a trait predicate, we can skip the "self" type.
191
                        data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty())
192 193 194 195 196 197 198
                    }
                    ty::Predicate::Projection(..) |
                    ty::Predicate::WellFormed(..) |
                    ty::Predicate::ObjectSafe(..) |
                    ty::Predicate::TypeOutlives(..) |
                    ty::Predicate::RegionOutlives(..) |
                    ty::Predicate::ClosureKind(..) |
N
Niko Matsakis 已提交
199
                    ty::Predicate::Subtype(..) |
200
                    ty::Predicate::ConstEvaluatable(..) => {
201 202
                        false
                    }
203
                }
204 205
            })
    }
206

207
    fn trait_has_sized_self(self, trait_def_id: DefId) -> bool {
208
        self.generics_require_sized_self(trait_def_id)
209
    }
210

211
    fn generics_require_sized_self(self, def_id: DefId) -> bool {
212
        let sized_def_id = match self.lang_items().sized_trait() {
213 214 215 216 217
            Some(def_id) => def_id,
            None => { return false; /* No Sized trait, can't require it! */ }
        };

        // Search for a predicate like `Self : Sized` amongst the trait bounds.
218
        let predicates = self.predicates_of(def_id);
219
        let predicates = predicates.instantiate_identity(self).predicates;
220
        elaborate_predicates(self, predicates)
221 222 223
            .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()
224
                }
225 226 227 228 229 230 231 232 233 234 235 236 237
                ty::Predicate::Projection(..) |
                ty::Predicate::Trait(..) |
                ty::Predicate::Subtype(..) |
                ty::Predicate::RegionOutlives(..) |
                ty::Predicate::WellFormed(..) |
                ty::Predicate::ObjectSafe(..) |
                ty::Predicate::ClosureKind(..) |
                ty::Predicate::TypeOutlives(..) |
                ty::Predicate::ConstEvaluatable(..) => {
                    false
                }
            }
        )
238 239 240 241 242
    }

    /// Returns `Some(_)` if this method makes the containing trait not object safe.
    fn object_safety_violation_for_method(self,
                                          trait_def_id: DefId,
243
                                          method: &ty::AssociatedItem)
244 245 246 247
                                          -> Option<MethodViolationCode>
    {
        // Any method that has a `Self : Sized` requisite is otherwise
        // exempt from the regulations.
248
        if self.generics_require_sized_self(method.def_id) {
249 250
            return None;
        }
251

252
        self.virtual_call_violation_for_method(trait_def_id, method)
253 254
    }

255 256 257 258 259 260
    /// We say a method is *vtable safe* if it can be invoked on a trait
    /// object.  Note that object-safe traits can have some
    /// non-vtable-safe methods, so long as they require `Self:Sized` or
    /// otherwise ensure that they cannot be used when `Self=Trait`.
    pub fn is_vtable_safe_method(self,
                                 trait_def_id: DefId,
261
                                 method: &ty::AssociatedItem)
262 263
                                 -> bool
    {
264
        // Any method that has a `Self : Sized` requisite can't be called.
265
        if self.generics_require_sized_self(method.def_id) {
266 267 268
            return false;
        }

269 270 271 272
        match self.virtual_call_violation_for_method(trait_def_id, method) {
            None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
            Some(_) => false,
        }
273
    }
274

275 276 277 278 279 280
    /// Returns `Some(_)` if this method cannot be called on a trait
    /// object; this does not necessarily imply that the enclosing trait
    /// is not object safe, because the method might have a where clause
    /// `Self:Sized`.
    fn virtual_call_violation_for_method(self,
                                         trait_def_id: DefId,
281
                                         method: &ty::AssociatedItem)
282 283
                                         -> Option<MethodViolationCode>
    {
284
        // The method's first parameter must be named `self`
285 286
        if !method.method_has_self_argument {
            return Some(MethodViolationCode::StaticMethod);
287 288
        }

289 290
        let sig = self.fn_sig(method.def_id);

291
        for input_ty in &sig.skip_binder().inputs()[1..] {
292 293 294
            if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                return Some(MethodViolationCode::ReferencesSelf);
            }
295
        }
296
        if self.contains_illegal_self_type_reference(trait_def_id, sig.output().skip_binder()) {
297
            return Some(MethodViolationCode::ReferencesSelf);
298
        }
299 300

        // We can't monomorphize things like `fn foo<A>(...)`.
V
varkor 已提交
301
        if self.generics_of(method.def_id).own_counts().types != 0 {
302
            return Some(MethodViolationCode::Generic);
303 304
        }

305 306 307
        if self.predicates_of(method.def_id).predicates.into_iter()
                // A trait object can't claim to live more than the concrete type,
                // so outlives predicates will always hold.
308
                .filter(|(p, _)| p.to_opt_type_outlives().is_none())
309 310 311 312
                .collect::<Vec<_>>()
                // Do a shallow visit so that `contains_illegal_self_type_reference`
                // may apply it's custom visiting.
                .visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t)) {
313 314
            let span = self.def_span(method.def_id);
            return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
315 316
        }

317 318 319 320 321
        let receiver_ty = self.liberate_late_bound_regions(
            method.def_id,
            &sig.map_bound(|sig| sig.inputs()[0]),
        );

322 323 324
        // until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
        // However, this is already considered object-safe. We allow it as a special case here.
        // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
325 326
        // `Receiver: Unsize<Receiver[Self => dyn Trait]>`
        if receiver_ty != self.mk_self_type() {
327
            if !self.receiver_is_dispatchable(method, receiver_ty) {
328
                return Some(MethodViolationCode::UndispatchableReceiver);
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
            } else {
                // sanity check to make sure the receiver actually has the layout of a pointer

                use ty::layout::Abi;

                let param_env = self.param_env(method.def_id);

                let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
                    match self.layout_of(param_env.and(ty)) {
                        Ok(layout) => &layout.abi,
                        Err(err) => bug!(
                            "Error: {}\n while computing layout for type {:?}", err, ty
                        )
                    }
                };

                // e.g. Rc<()>
                let unit_receiver_ty = self.receiver_for_self_ty(
                    receiver_ty, self.mk_unit(), method.def_id
                );

                match abi_of_ty(unit_receiver_ty) {
                    &Abi::Scalar(..) => (),
                    abi => bug!("Receiver when Self = () should have a Scalar ABI, found {:?}", abi)
                }

                let trait_object_ty = self.object_ty_for_trait(
                    trait_def_id, self.mk_region(ty::ReStatic)
                );

                // e.g. Rc<dyn Trait>
                let trait_object_receiver = self.receiver_for_self_ty(
                    receiver_ty, trait_object_ty, method.def_id
                );

                match abi_of_ty(trait_object_receiver) {
                    &Abi::ScalarPair(..) => (),
                    abi => bug!(
                        "Receiver when Self = {} should have a ScalarPair ABI, found {:?}",
                        trait_object_ty, abi
                    )
                }
371 372 373
            }
        }

374
        None
375 376
    }

377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
    /// performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
    /// e.g. for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`
    fn receiver_for_self_ty(
        self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
    ) -> Ty<'tcx> {
        let substs = Substs::for_item(self, method_def_id, |param, _| {
            if param.index == 0 {
                self_ty.into()
            } else {
                self.mk_param_from_def(param)
            }
        });

        receiver_ty.subst(self, substs)
    }

    /// creates the object type for the current trait. For example,
    /// if the current trait is `Deref`, then this will be
    /// `dyn Deref<Target=Self::Target> + 'static`
    fn object_ty_for_trait(self, trait_def_id: DefId, lifetime: ty::Region<'tcx>) -> Ty<'tcx> {
        debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);

        let trait_ref = ty::TraitRef::identity(self, trait_def_id);

        let trait_predicate = ty::ExistentialPredicate::Trait(
            ty::ExistentialTraitRef::erase_self_ty(self, trait_ref)
        );

        let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
            .flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
            .filter(|item| item.kind == ty::AssociatedKind::Type)
            .collect::<Vec<_>>();

        // existential predicates need to be in a specific order
        associated_types.sort_by_key(|item| self.def_path_hash(item.def_id));

        let projection_predicates = associated_types.into_iter().map(|item| {
            ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
                ty: self.mk_projection(item.def_id, trait_ref.substs),
                item_def_id: item.def_id,
                substs: trait_ref.substs,
            })
        });

        let existential_predicates = self.mk_existential_predicates(
            iter::once(trait_predicate).chain(projection_predicates)
        );

        let object_ty = self.mk_dynamic(
            ty::Binder::dummy(existential_predicates),
            lifetime,
        );

        debug!("object_ty_for_trait: object_ty=`{}`", object_ty);

        object_ty
    }

435 436 437
    /// checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
    /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
    /// in the following way:
438 439
    /// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`
    /// - require the following bound:
440 441 442 443
    ///
    ///        Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
    ///
    ///    where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
444 445 446
    ///   (substitution notation).
    ///
    /// some examples of receiver types and their required obligation
447 448 449
    /// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`
    /// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`
    /// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`
450
    ///
451
    /// The only case where the receiver is not dispatchable, but is still a valid receiver
452 453
    /// type (just not object-safe), is when there is more than one level of pointer indirection.
    /// e.g. `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
454 455 456 457
    /// is no way, or at least no inexpensive way, to coerce the receiver from the version where
    /// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
    /// contained by the trait object, because the object that needs to be coerced is behind
    /// a pointer.
458
    ///
459 460 461 462
    /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
    /// in a new check that `Trait` is object safe, creating a cycle. So instead, we fudge a little
    /// by introducing a new type parameter `U` such that `Self: Unsize<U>` and `U: Trait + ?Sized`,
    /// and use `U` in place of `dyn Trait`. Written as a chalk-style query:
463
    ///
464
    ///     forall (U: Trait + ?Sized) {
465
    ///         if (Self: Unsize<U>) {
466
    ///             Receiver: DispatchFromDyn<Receiver[Self => U]>
467 468 469
    ///         }
    ///     }
    ///
470 471 472
    /// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
    /// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
    /// for `self: Pin<Box<Self>>, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
473 474 475 476 477
    //
    // FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
    // fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
    // `self: Wrapper<Self>`.
    #[allow(dead_code)]
478
    fn receiver_is_dispatchable(
479 480 481 482
        self,
        method: &ty::AssociatedItem,
        receiver_ty: Ty<'tcx>,
    ) -> bool {
483
        debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
484 485

        let traits = (self.lang_items().unsize_trait(),
486 487
                      self.lang_items().dispatch_from_dyn_trait());
        let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
488 489
            (u, cu)
        } else {
490
            debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
491 492 493
            return false;
        };

494
        // the type `U` in the query
495 496 497
        // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
        // FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries
        // are implemented
498
        let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
499 500 501 502
            ::std::u32::MAX,
            Name::intern("RustaceansAreAwesome").as_interned_str(),
        );

503 504 505 506 507 508 509
        // `Receiver[Self => U]`
        let unsized_receiver_ty = self.receiver_for_self_ty(
            receiver_ty, unsized_self_ty, method.def_id
        );

        // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
        // `U: ?Sized` is already implied here
510 511 512
        let param_env = {
            let mut param_env = self.param_env(method.def_id);

513 514
            // Self: Unsize<U>
            let unsize_predicate = ty::TraitRef {
515
                def_id: unsize_did,
516
                substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
517 518
            }.to_predicate();

519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
            // U: Trait<Arg1, ..., ArgN>
            let trait_predicate = {
                let substs = Substs::for_item(self, method.container.assert_trait(), |param, _| {
                    if param.index == 0 {
                        unsized_self_ty.into()
                    } else {
                        self.mk_param_from_def(param)
                    }
                });

                ty::TraitRef {
                    def_id: unsize_did,
                    substs,
                }.to_predicate()
            };

535
            let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter().cloned()
536 537
                .chain(iter::once(unsize_predicate))
                .chain(iter::once(trait_predicate))
538 539 540 541 542 543 544
                .collect();

            param_env.caller_bounds = self.intern_predicates(&caller_bounds);

            param_env
        };

545
        // Receiver: DispatchFromDyn<Receiver[Self => U]>
546 547
        let obligation = {
            let predicate = ty::TraitRef {
548 549
                def_id: dispatch_from_dyn_did,
                substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
550 551 552 553 554 555 556 557 558 559
            }.to_predicate();

            Obligation::new(
                ObligationCause::dummy(),
                param_env,
                predicate,
            )
        };

        self.infer_ctxt().enter(|ref infcx| {
560
            // the receiver is dispatchable iff the obligation holds
561 562 563 564
            infcx.predicate_must_hold(&obligation)
        })
    }

565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    fn contains_illegal_self_type_reference(self,
                                            trait_def_id: DefId,
                                            ty: Ty<'tcx>)
                                            -> bool
    {
        // This is somewhat subtle. In general, we want to forbid
        // references to `Self` in the argument and return types,
        // since the value of `Self` is erased. However, there is one
        // exception: it is ok to reference `Self` in order to access
        // an associated type of the current trait, since we retain
        // the value of those associated types in the object type
        // itself.
        //
        // ```rust
        // trait SuperTrait {
        //     type X;
        // }
        //
        // trait Trait : SuperTrait {
        //     type Y;
        //     fn foo(&self, x: Self) // bad
        //     fn foo(&self) -> Self // bad
        //     fn foo(&self) -> Option<Self> // bad
        //     fn foo(&self) -> Self::Y // OK, desugars to next example
        //     fn foo(&self) -> <Self as Trait>::Y // OK
        //     fn foo(&self) -> Self::X // OK, desugars to next example
        //     fn foo(&self) -> <Self as SuperTrait>::X // OK
        // }
        // ```
        //
        // However, it is not as simple as allowing `Self` in a projected
        // type, because there are illegal ways to use `Self` as well:
        //
        // ```rust
        // trait Trait : SuperTrait {
        //     ...
        //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
        // }
        // ```
        //
        // Here we will not have the type of `X` recorded in the
        // object type, and we cannot resolve `Self as SomeOtherTrait`
        // without knowing what `Self` is.

        let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
        let mut error = false;
        ty.maybe_walk(|ty| {
            match ty.sty {
V
varkor 已提交
613
                ty::Param(ref param_ty) => {
614
                    if param_ty.is_self() {
615 616 617 618
                        error = true;
                    }

                    false // no contained types to walk
619 620
                }

V
varkor 已提交
621
                ty::Projection(ref data) => {
622 623 624 625
                    // This is a projected type `<Foo as SomeTrait>::X`.

                    // Compute supertraits of current trait lazily.
                    if supertraits.is_none() {
626 627 628
                        let trait_ref = ty::Binder::bind(
                            ty::TraitRef::identity(self, trait_def_id),
                        );
629 630 631 632 633 634 635 636 637 638 639
                        supertraits = Some(traits::supertraits(self, trait_ref).collect());
                    }

                    // Determine whether the trait reference `Foo as
                    // SomeTrait` is in fact a supertrait of the
                    // current trait. In that case, this type is
                    // legal, because the type `X` will be specified
                    // in the object type.  Note that we can just use
                    // direct equality here because all of these types
                    // are part of the formal parameter listing, and
                    // hence there should be no inference variables.
640
                    let projection_trait_ref = ty::Binder::bind(data.trait_ref(self));
641 642 643 644 645 646 647 648
                    let is_supertrait_of_current_trait =
                        supertraits.as_ref().unwrap().contains(&projection_trait_ref);

                    if is_supertrait_of_current_trait {
                        false // do not walk contained types, do not report error, do collect $200
                    } else {
                        true // DO walk contained types, POSSIBLY reporting an error
                    }
649 650
                }

651
                _ => true, // walk contained types, if any
652
            }
653
        });
654

655 656
        error
    }
657
}
658 659

pub(super) fn is_object_safe_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
V
varkor 已提交
660
                                                trait_def_id: DefId) -> bool {
661 662
    tcx.object_safety_violations(trait_def_id).is_empty()
}