Skip to content

Commit 904c61f

Browse files
committed
institute new rules, without correctness check
* `#[rustc_dyn]` attribute on traits opts them in to old rules * otherwise, trait is not dyn safe is implemented for all types
1 parent 87cbf0a commit 904c61f

File tree

7 files changed

+81
-3
lines changed

7 files changed

+81
-3
lines changed

src/libcore/any.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ use crate::intrinsics;
7575
///
7676
/// [mod]: index.html
7777
#[stable(feature = "rust1", since = "1.0.0")]
78+
#[cfg_attr(not(bootstrap), rustc_dyn)]
7879
pub trait Any: 'static {
7980
/// Gets the `TypeId` of `self`.
8081
///

src/libcore/borrow.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
/// [`String`]: ../../std/string/struct.String.html
158158
/// [`str`]: ../../std/primitive.str.html
159159
#[stable(feature = "rust1", since = "1.0.0")]
160+
#[cfg_attr(not(bootstrap), rustc_dyn)]
160161
pub trait Borrow<Borrowed: ?Sized> {
161162
/// Immutably borrows from an owned value.
162163
///
@@ -189,6 +190,7 @@ pub trait Borrow<Borrowed: ?Sized> {
189190
///
190191
/// [`Borrow<T>`]: trait.Borrow.html
191192
#[stable(feature = "rust1", since = "1.0.0")]
193+
#[cfg_attr(not(bootstrap), rustc_dyn)]
192194
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
193195
/// Mutably borrows from an owned value.
194196
///

src/librustc/traits/object_safety.rs

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ use crate::hir;
1414
use crate::hir::def_id::DefId;
1515
use crate::lint;
1616
use crate::traits::{self, Obligation, ObligationCause};
17-
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate};
17+
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate, ParamTy};
1818
use crate::ty::subst::{Subst, InternalSubsts};
1919
use std::borrow::Cow;
2020
use std::iter::{self};
2121
use syntax::ast::{self};
2222
use syntax::symbol::Symbol;
2323
use syntax_pos::{Span, DUMMY_SP};
24+
use syntax::symbol::sym;
2425

2526
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
2627
pub enum ObjectSafetyViolation {
@@ -281,7 +282,40 @@ impl<'tcx> TyCtxt<'tcx> {
281282
false
282283
}
283284
}
284-
)
285+
)
286+
}
287+
288+
fn generics_require_sized_param(self, def_id: DefId, param_ty: ParamTy) -> bool {
289+
debug!("generics_require_sized_param(def_id={:?}, param_ty={:?})", def_id, param_ty);
290+
291+
let sized_def_id = match self.lang_items().sized_trait() {
292+
Some(def_id) => def_id,
293+
None => { return false; /* No Sized trait, can't require it! */ }
294+
};
295+
296+
// Search for a predicate like `Self : Sized` amongst the trait bounds.
297+
let predicates = self.predicates_of(def_id);
298+
let predicates = predicates.instantiate_identity(self).predicates;
299+
predicates
300+
.iter()
301+
.any(|predicate| match predicate {
302+
ty::Predicate::Trait(ref trait_pred) => {
303+
debug!("generics_require_sized_param: trait_pred = {:?}", trait_pred);
304+
305+
trait_pred.def_id() == sized_def_id
306+
&& trait_pred.skip_binder().self_ty().is_param(param_ty.index)
307+
}
308+
ty::Predicate::Projection(..) |
309+
ty::Predicate::Subtype(..) |
310+
ty::Predicate::RegionOutlives(..) |
311+
ty::Predicate::WellFormed(..) |
312+
ty::Predicate::ObjectSafe(..) |
313+
ty::Predicate::ClosureKind(..) |
314+
ty::Predicate::TypeOutlives(..) |
315+
ty::Predicate::ConstEvaluatable(..) => {
316+
false
317+
}
318+
})
285319
}
286320

287321
/// Returns `Some(_)` if this method makes the containing trait not object safe.
@@ -724,8 +758,43 @@ impl<'tcx> TyCtxt<'tcx> {
724758

725759
error
726760
}
761+
762+
/// Searches for an impl that potentially overlaps `dyn Trait`
763+
/// (where `Trait` is the trait with def-id `trait_def_id`). This
764+
/// is used to distinguish between a trait being **fully**
765+
/// object-safe and being **degenerate** object-safe -- the latter
766+
/// means that we permit `dyn Foo` but we do not supply a `dyn
767+
/// Foo: Foo` impl.
768+
fn impl_potentially_overlapping_dyn_trait(self, tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
769+
debug!("impl_potentially_overlapping_dyn_trait({:?})", trait_def_id);
770+
let mut found_match = false;
771+
tcx.for_each_impl(trait_def_id, |impl_def_id| {
772+
let impl_self_ty = tcx.type_of(impl_def_id);
773+
match impl_self_ty.kind {
774+
ty::Param(param_ty) => {
775+
if !self.generics_require_sized_param(impl_def_id, param_ty) {
776+
found_match = true;
777+
debug!("Match found = {}; for param_ty {}", found_match, param_ty.name);
778+
tcx.sess.span_warn(
779+
self.def_span(impl_def_id),
780+
"impl_potentially_overlapping_dyn_trait",
781+
);
782+
}
783+
}
784+
_ => ()
785+
}
786+
});
787+
788+
found_match
789+
}
727790
}
728791

729792
pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
730-
tcx.object_safety_violations(trait_def_id).is_empty()
793+
tcx.object_safety_violations(trait_def_id).is_empty() && {
794+
if tcx.has_attr(trait_def_id, sym::rustc_dyn) {
795+
true
796+
} else {
797+
!tcx.impl_potentially_overlapping_dyn_trait(tcx, trait_def_id)
798+
}
799+
}
731800
}

src/librustc_data_structures/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#![feature(integer_atomics)]
2525
#![feature(test)]
2626
#![feature(associated_type_bounds)]
27+
#![feature(rustc_attrs)]
2728

2829
#![cfg_attr(unix, feature(libc))]
2930

src/librustc_data_structures/sync.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ pub use std::sync::atomic::Ordering;
2828

2929
cfg_if! {
3030
if #[cfg(not(parallel_compiler))] {
31+
#[cfg_attr(not(bootstrap), rustc_dyn)]
3132
pub auto trait Send {}
33+
34+
#[cfg_attr(not(bootstrap), rustc_dyn)]
3235
pub auto trait Sync {}
3336

3437
impl<T: ?Sized> Send for T {}

src/libsyntax/feature_gate/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
532532
// Internal attributes, Testing:
533533
// ==========================================================================
534534

535+
rustc_attr!(TEST, rustc_dyn, Whitelisted, template!(Word)),
535536
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)),
536537
rustc_attr!(TEST, rustc_variance, Normal, template!(Word)),
537538
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ symbols! {
583583
rustc_dump_env_program_clauses,
584584
rustc_dump_program_clauses,
585585
rustc_dump_user_substs,
586+
rustc_dyn,
586587
rustc_error,
587588
rustc_expected_cgu_reuse,
588589
rustc_if_this_changed,

0 commit comments

Comments
 (0)