Skip to content

Commit 3b13b9c

Browse files
committed
rollup merge of rust-lang#23638: pnkfelix/fsk-reject-specialized-drops
Reject specialized Drop impls. See Issue rust-lang#8142 for discussion. This makes it illegal for a Drop impl to be more specialized than the original item. So for example, all of the following are now rejected (when they would have been blindly accepted before): ```rust struct S<A> { ... }; impl Drop for S<i8> { ... } // error: specialized to concrete type struct T<'a> { ... }; impl Drop for T<'static> { ... } // error: specialized to concrete region struct U<A> { ... }; impl<A:Clone> Drop for U<A> { ... } // error: added extra type requirement struct V<'a,'b>; impl<'a,'b:a> Drop for V<'a,'b> { ... } // error: added extra region requirement ``` Due to examples like the above, this is a [breaking-change]. (The fix is to either remove the specialization from the `Drop` impl, or to transcribe the requirements into the struct/enum definition; examples of both are shown in the PR's fixed to `libstd`.) ---- This is likely to be the last thing blocking the removal of the `#[unsafe_destructor]` attribute. Fix rust-lang#8142 Fix rust-lang#23584
2 parents 91b633a + 1955e05 commit 3b13b9c

File tree

27 files changed

+465
-63
lines changed

27 files changed

+465
-63
lines changed

src/doc/trpl/unsafe.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,16 @@ use std::ptr;
197197
198198
// Define a wrapper around the handle returned by the foreign code.
199199
// Unique<T> has the same semantics as Box<T>
200-
pub struct Unique<T> {
200+
//
201+
// NB: For simplicity and correctness, we require that T has kind Send
202+
// (owned boxes relax this restriction).
203+
pub struct Unique<T: Send> {
201204
// It contains a single raw, mutable pointer to the object in question.
202205
ptr: *mut T
203206
}
204207
205208
// Implement methods for creating and using the values in the box.
206209
207-
// NB: For simplicity and correctness, we require that T has kind Send
208-
// (owned boxes relax this restriction).
209210
impl<T: Send> Unique<T> {
210211
pub fn new(value: T) -> Unique<T> {
211212
unsafe {
@@ -239,11 +240,11 @@ impl<T: Send> Unique<T> {
239240
// Unique<T>, making the struct manage the raw pointer: when the
240241
// struct goes out of scope, it will automatically free the raw pointer.
241242
//
242-
// NB: This is an unsafe destructor, because rustc will not normally
243-
// allow destructors to be associated with parameterized types, due to
244-
// bad interaction with managed boxes. (With the Send restriction,
245-
// we don't have this problem.) Note that the `#[unsafe_destructor]`
246-
// feature gate is required to use unsafe destructors.
243+
// NB: This is an unsafe destructor; rustc will not normally allow
244+
// destructors to be associated with parameterized types (due to
245+
// historically failing to check them soundly). Note that the
246+
// `#[unsafe_destructor]` feature gate is currently required to use
247+
// unsafe destructors.
247248
#[unsafe_destructor]
248249
impl<T: Send> Drop for Unique<T> {
249250
fn drop(&mut self) {

src/liballoc/arc.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ impl<T: Send + Sync + Clone> Arc<T> {
321321

322322
#[unsafe_destructor]
323323
#[stable(feature = "rust1", since = "1.0.0")]
324-
impl<T: Sync + Send> Drop for Arc<T> {
324+
impl<T> Drop for Arc<T> {
325325
/// Drops the `Arc<T>`.
326326
///
327327
/// This will decrement the strong reference count. If the strong reference
@@ -388,7 +388,7 @@ impl<T: Sync + Send> Drop for Arc<T> {
388388

389389
#[unstable(feature = "alloc",
390390
reason = "Weak pointers may not belong in this module.")]
391-
impl<T: Sync + Send> Weak<T> {
391+
impl<T> Weak<T> {
392392
/// Upgrades a weak reference to a strong reference.
393393
///
394394
/// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
@@ -454,7 +454,7 @@ impl<T: Sync + Send> Clone for Weak<T> {
454454

455455
#[unsafe_destructor]
456456
#[stable(feature = "rust1", since = "1.0.0")]
457-
impl<T: Sync + Send> Drop for Weak<T> {
457+
impl<T> Drop for Weak<T> {
458458
/// Drops the `Weak<T>`.
459459
///
460460
/// This will decrement the weak reference count.

src/librustc/middle/infer/higher_ranked/mod.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType, SkolemizationMap};
1515
use super::combine::{Combine, Combineable};
1616

17+
use middle::subst;
1718
use middle::ty::{self, Binder};
1819
use middle::ty_fold::{self, TypeFoldable};
1920
use syntax::codemap::Span;
@@ -455,6 +456,63 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
455456
}
456457
}
457458

459+
/// Constructs and returns a substitution that, for a given type
460+
/// scheme parameterized by `generics`, will replace every generic
461+
/// parmeter in the type with a skolemized type/region (which one can
462+
/// think of as a "fresh constant", except at the type/region level of
463+
/// reasoning).
464+
///
465+
/// Since we currently represent bound/free type parameters in the
466+
/// same way, this only has an effect on regions.
467+
///
468+
/// (Note that unlike a substitution from `ty::construct_free_substs`,
469+
/// this inserts skolemized regions rather than free regions; this
470+
/// allows one to use `fn leak_check` to catch attmepts to unify the
471+
/// skolemized regions with e.g. the `'static` lifetime)
472+
pub fn construct_skolemized_substs<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
473+
generics: &ty::Generics<'tcx>,
474+
snapshot: &CombinedSnapshot)
475+
-> (subst::Substs<'tcx>, SkolemizationMap)
476+
{
477+
let mut map = FnvHashMap();
478+
479+
// map T => T
480+
let mut types = subst::VecPerParamSpace::empty();
481+
push_types_from_defs(infcx.tcx, &mut types, generics.types.as_slice());
482+
483+
// map early- or late-bound 'a => fresh 'a
484+
let mut regions = subst::VecPerParamSpace::empty();
485+
push_region_params(infcx, &mut map, &mut regions, generics.regions.as_slice(), snapshot);
486+
487+
let substs = subst::Substs { types: types,
488+
regions: subst::NonerasedRegions(regions) };
489+
return (substs, map);
490+
491+
fn push_region_params<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
492+
map: &mut SkolemizationMap,
493+
regions: &mut subst::VecPerParamSpace<ty::Region>,
494+
region_params: &[ty::RegionParameterDef],
495+
snapshot: &CombinedSnapshot)
496+
{
497+
for r in region_params {
498+
let br = r.to_bound_region();
499+
let skol_var = infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot);
500+
let sanity_check = map.insert(br, skol_var);
501+
assert!(sanity_check.is_none());
502+
regions.push(r.space, skol_var);
503+
}
504+
}
505+
506+
fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
507+
types: &mut subst::VecPerParamSpace<ty::Ty<'tcx>>,
508+
defs: &[ty::TypeParameterDef<'tcx>]) {
509+
for def in defs {
510+
let ty = ty::mk_param_from_def(tcx, def);
511+
types.push(def.space, ty);
512+
}
513+
}
514+
}
515+
458516
pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
459517
binder: &ty::Binder<T>,
460518
snapshot: &CombinedSnapshot)

src/librustc/middle/infer/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
726726
})
727727
}
728728

729+
pub fn construct_skolemized_subst(&self,
730+
generics: &ty::Generics<'tcx>,
731+
snapshot: &CombinedSnapshot)
732+
-> (subst::Substs<'tcx>, SkolemizationMap) {
733+
/*! See `higher_ranked::construct_skolemized_subst` */
734+
735+
higher_ranked::construct_skolemized_substs(self, generics, snapshot)
736+
}
737+
729738
pub fn skolemize_late_bound_regions<T>(&self,
730739
value: &ty::Binder<T>,
731740
snapshot: &CombinedSnapshot)

src/librustc/middle/ty.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,6 +1793,9 @@ impl RegionParameterDef {
17931793
pub fn to_early_bound_region(&self) -> ty::Region {
17941794
ty::ReEarlyBound(self.def_id.node, self.space, self.index, self.name)
17951795
}
1796+
pub fn to_bound_region(&self) -> ty::BoundRegion {
1797+
ty::BoundRegion::BrNamed(self.def_id, self.name)
1798+
}
17961799
}
17971800

17981801
/// Information about the formal type/lifetime parameters associated

0 commit comments

Comments
 (0)