Skip to content

Commit bcda58f

Browse files
committed
Auto merge of #31710 - eddyb:reify, r=nikomatsakis
Distinguish fn item types to allow reification from nothing to fn pointers. The first commit is a rebase of #26284, except for files that have moved since. This is a [breaking-change], due to: * each FFI function has a distinct type, like all other functions currently do * all generic parameters on functions are recorded in their item types, e.g.: `size_of::<u8>` & `size_of::<i8>`'s types differ despite their identical signature. * function items are zero-sized, which will stop transmutes from working on them The first two cases are handled in most cases with the new coerce-unify logic, which will combine incompatible function item types into function pointers, at the outer-most level of if-else chains, match arms and array literals. The last case is specially handled during type-checking such that transmutes from a function item type to a pointer or integer type will continue to work for another release cycle, but are being linted against. To get rid of warnings and ensure your code will continue to compile, cast to a pointer before transmuting.
2 parents 0b9995b + 3855fa9 commit bcda58f

File tree

109 files changed

+2056
-2242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+2056
-2242
lines changed

src/librustc/lint/builtin.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ declare_lint! {
148148
"uses of #[derive] with raw pointers are rarely correct"
149149
}
150150

151+
declare_lint! {
152+
pub TRANSMUTE_FROM_FN_ITEM_TYPES,
153+
Warn,
154+
"transmute from function item type to pointer-sized type erroneously allowed"
155+
}
156+
151157
/// Does nothing as a lint pass, but registers some `Lint`s
152158
/// which are used by other parts of the compiler.
153159
#[derive(Copy, Clone)]
@@ -177,7 +183,8 @@ impl LintPass for HardwiredLints {
177183
INVALID_TYPE_PARAM_DEFAULT,
178184
MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
179185
CONST_ERR,
180-
RAW_POINTER_DERIVE
186+
RAW_POINTER_DERIVE,
187+
TRANSMUTE_FROM_FN_ITEM_TYPES
181188
)
182189
}
183190
}

src/librustc/lint/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,9 @@ pub fn check_crate(tcx: &TyCtxt, access_levels: &AccessLevels) {
12871287
}
12881288

12891289
*tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner();
1290+
1291+
// Put the lint store back in the session.
1292+
mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), cx.lints);
12901293
}
12911294

12921295
pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {

src/librustc/middle/effect.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ enum RootUnsafeContext {
4444

4545
fn type_is_unsafe_function(ty: Ty) -> bool {
4646
match ty.sty {
47-
ty::TyBareFn(_, ref f) => f.unsafety == hir::Unsafety::Unsafe,
47+
ty::TyFnDef(_, _, ref f) |
48+
ty::TyFnPtr(ref f) => f.unsafety == hir::Unsafety::Unsafe,
4849
_ => false,
4950
}
5051
}

src/librustc/middle/expr_use_visitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
556556
callee, callee_ty);
557557
let call_scope = self.tcx().region_maps.node_extent(call.id);
558558
match callee_ty.sty {
559-
ty::TyBareFn(..) => {
559+
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
560560
self.consume_expr(callee);
561561
}
562562
ty::TyError => { }

src/librustc/middle/infer/freshen.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
161161
ty::TySlice(..) |
162162
ty::TyRawPtr(..) |
163163
ty::TyRef(..) |
164-
ty::TyBareFn(..) |
164+
ty::TyFnDef(..) |
165+
ty::TyFnPtr(_) |
165166
ty::TyTrait(..) |
166167
ty::TyStruct(..) |
167168
ty::TyClosure(..) |

src/librustc/middle/infer/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
454454
-> UnitResult<'tcx>
455455
{
456456
debug!("mk_eqty({:?} <: {:?})", a, b);
457-
cx.commit_if_ok(|_| cx.eq_types(a_is_expected, origin, a, b))
457+
cx.eq_types(a_is_expected, origin, a, b)
458458
}
459459

460460
pub fn mk_eq_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -466,7 +466,7 @@ pub fn mk_eq_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
466466
{
467467
debug!("mk_eq_trait_refs({:?} <: {:?})",
468468
a, b);
469-
cx.commit_if_ok(|_| cx.eq_trait_refs(a_is_expected, origin, a.clone(), b.clone()))
469+
cx.eq_trait_refs(a_is_expected, origin, a, b)
470470
}
471471

472472
pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -478,7 +478,7 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
478478
{
479479
debug!("mk_sub_poly_trait_refs({:?} <: {:?})",
480480
a, b);
481-
cx.commit_if_ok(|_| cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone()))
481+
cx.sub_poly_trait_refs(a_is_expected, origin, a, b)
482482
}
483483

484484
fn expected_found<T>(a_is_expected: bool,
@@ -1351,18 +1351,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13511351
}
13521352

13531353
pub fn report_mismatched_types(&self,
1354-
span: Span,
1354+
origin: TypeOrigin,
13551355
expected: Ty<'tcx>,
13561356
actual: Ty<'tcx>,
1357-
err: &TypeError<'tcx>) {
1357+
err: TypeError<'tcx>) {
13581358
let trace = TypeTrace {
1359-
origin: TypeOrigin::Misc(span),
1359+
origin: origin,
13601360
values: Types(ExpectedFound {
13611361
expected: expected,
13621362
found: actual
13631363
})
13641364
};
1365-
self.report_and_explain_type_error(trace, err);
1365+
self.report_and_explain_type_error(trace, &err);
13661366
}
13671367

13681368
pub fn report_conflicting_default_types(&self,

src/librustc/middle/intrinsicck.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use dep_graph::DepNode;
1212
use middle::def::Def;
1313
use middle::def_id::DefId;
1414
use middle::subst::{Subst, Substs, EnumeratedItems};
15-
use middle::ty::{TransmuteRestriction, TyCtxt, TyBareFn};
15+
use middle::ty::{TransmuteRestriction, TyCtxt};
1616
use middle::ty::{self, Ty, TypeFoldable};
1717

1818
use std::fmt;
@@ -53,7 +53,7 @@ struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {
5353
impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
5454
fn def_id_is_transmute(&self, def_id: DefId) -> bool {
5555
let intrinsic = match self.tcx.lookup_item_type(def_id).ty.sty {
56-
ty::TyBareFn(_, ref bfty) => bfty.abi == RustIntrinsic,
56+
ty::TyFnDef(_, _, ref bfty) => bfty.abi == RustIntrinsic,
5757
_ => return false
5858
};
5959
intrinsic && self.tcx.item_name(def_id).as_str() == "transmute"
@@ -238,7 +238,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
238238
Def::Fn(did) if self.def_id_is_transmute(did) => {
239239
let typ = self.tcx.node_id_to_type(expr.id);
240240
match typ.sty {
241-
TyBareFn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
241+
ty::TyFnDef(_, _, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
242242
if let ty::FnConverging(to) = bare_fn_ty.sig.0.output {
243243
let from = bare_fn_ty.sig.0.inputs[0];
244244
self.check_transmute(expr.span, from, to, expr.id);

src/librustc/middle/subst.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ impl<'tcx> Substs<'tcx> {
148148
Substs { types: types, regions: regions }
149149
}
150150

151-
pub fn with_method_from(self,
151+
pub fn with_method_from(&self,
152152
meth_substs: &Substs<'tcx>)
153153
-> Substs<'tcx>
154154
{
155-
let Substs { types, regions } = self;
155+
let Substs { types, regions } = self.clone();
156156
let types = types.with_slice(FnSpace, meth_substs.types.get_slice(FnSpace));
157157
let regions = regions.map(|r| {
158158
r.with_slice(FnSpace, meth_substs.regions().get_slice(FnSpace))

src/librustc/middle/traits/coherence.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ fn ty_is_local_constructor<'tcx>(tcx: &TyCtxt<'tcx>,
301301
ty::TyUint(..) |
302302
ty::TyFloat(..) |
303303
ty::TyStr |
304-
ty::TyBareFn(..) |
304+
ty::TyFnDef(..) |
305+
ty::TyFnPtr(_) |
305306
ty::TyArray(..) |
306307
ty::TySlice(..) |
307308
ty::TyRawPtr(..) |

src/librustc/middle/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ pub enum Vtable<'tcx, N> {
278278
#[derive(Clone, PartialEq, Eq)]
279279
pub struct VtableImplData<'tcx, N> {
280280
pub impl_def_id: DefId,
281-
pub substs: subst::Substs<'tcx>,
281+
pub substs: &'tcx subst::Substs<'tcx>,
282282
pub nested: Vec<N>
283283
}
284284

src/librustc/middle/traits/project.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ fn confirm_impl_candidate<'cx,'tcx>(
948948
for impl_item in &selcx.tcx().impl_items.borrow()[&impl_vtable.impl_def_id] {
949949
if let ty::TypeTraitItem(ref assoc_ty) = impl_or_trait_items_map[&impl_item.def_id()] {
950950
if assoc_ty.name == obligation.predicate.item_name {
951-
return (assoc_ty.ty.unwrap().subst(selcx.tcx(), &impl_vtable.substs),
951+
return (assoc_ty.ty.unwrap().subst(selcx.tcx(), impl_vtable.substs),
952952
impl_vtable.nested);
953953
}
954954
}

src/librustc/middle/traits/select.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12861286
}
12871287

12881288
// provide an impl, but only for suitable `fn` pointers
1289-
ty::TyBareFn(_, &ty::BareFnTy {
1289+
ty::TyFnDef(_, _, &ty::BareFnTy {
1290+
unsafety: hir::Unsafety::Normal,
1291+
abi: Abi::Rust,
1292+
sig: ty::Binder(ty::FnSig {
1293+
inputs: _,
1294+
output: ty::FnConverging(_),
1295+
variadic: false
1296+
})
1297+
}) |
1298+
ty::TyFnPtr(&ty::BareFnTy {
12901299
unsafety: hir::Unsafety::Normal,
12911300
abi: Abi::Rust,
12921301
sig: ty::Binder(ty::FnSig {
@@ -1646,7 +1655,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16461655
ty::TyInt(_) |
16471656
ty::TyBool |
16481657
ty::TyFloat(_) |
1649-
ty::TyBareFn(..) |
1658+
ty::TyFnDef(..) |
1659+
ty::TyFnPtr(_) |
16501660
ty::TyChar => {
16511661
// safe for everything
16521662
ok_if(Vec::new())
@@ -1850,7 +1860,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
18501860
ty::TyInt(_) |
18511861
ty::TyBool |
18521862
ty::TyFloat(_) |
1853-
ty::TyBareFn(..) |
1863+
ty::TyFnDef(..) |
1864+
ty::TyFnPtr(_) |
18541865
ty::TyStr |
18551866
ty::TyError |
18561867
ty::TyInfer(ty::IntVar(_)) |
@@ -2294,7 +2305,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
22942305
impl_obligations.append(&mut substs.obligations);
22952306

22962307
VtableImplData { impl_def_id: impl_def_id,
2297-
substs: substs.value,
2308+
substs: self.tcx().mk_substs(substs.value),
22982309
nested: impl_obligations }
22992310
}
23002311

src/librustc/middle/traits/structural_impls.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,10 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
147147

148148
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
149149
fn super_fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
150+
let substs = self.substs.fold_with(folder);
150151
traits::VtableImplData {
151152
impl_def_id: self.impl_def_id,
152-
substs: self.substs.fold_with(folder),
153+
substs: folder.tcx().mk_substs(substs),
153154
nested: self.nested.fold_with(folder),
154155
}
155156
}

src/librustc/middle/ty/adjustment.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ impl<'tcx> ty::TyS<'tcx> {
155155
match *adjustment {
156156
AdjustReifyFnPointer => {
157157
match self.sty {
158-
ty::TyBareFn(Some(_), b) => {
159-
cx.mk_fn(None, b)
158+
ty::TyFnDef(_, _, b) => {
159+
cx.mk_ty(ty::TyFnPtr(b))
160160
}
161161
_ => {
162162
cx.sess.bug(
@@ -168,7 +168,7 @@ impl<'tcx> ty::TyS<'tcx> {
168168

169169
AdjustUnsafeFnPointer => {
170170
match self.sty {
171-
ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
171+
ty::TyFnPtr(b) => cx.safe_to_unsafe_fn_ty(b),
172172
ref b => {
173173
cx.sess.bug(
174174
&format!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: \

src/librustc/middle/ty/cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl<'tcx> CastTy<'tcx> {
6969
Some(CastTy::Int(IntTy::CEnum)),
7070
ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
7171
ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
72-
ty::TyBareFn(..) => Some(CastTy::FnPtr),
72+
ty::TyFnPtr(..) => Some(CastTy::FnPtr),
7373
_ => None,
7474
}
7575
}

src/librustc/middle/ty/contents.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ impl<'tcx> ty::TyS<'tcx> {
187187
// Scalar and unique types are sendable, and durable
188188
ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
189189
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
190-
ty::TyBareFn(..) | ty::TyChar => {
190+
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => {
191191
TC::None
192192
}
193193

src/librustc/middle/ty/context.rs

+12-26
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ use std::borrow::Borrow;
4141
use std::cell::{Cell, RefCell, Ref};
4242
use std::hash::{Hash, Hasher};
4343
use std::rc::Rc;
44-
use syntax::abi::Abi;
4544
use syntax::ast::{self, Name, NodeId};
4645
use syntax::attr;
4746
use syntax::parse::token::special_idents;
@@ -734,8 +733,8 @@ impl<'tcx> TyCtxt<'tcx> {
734733
pub fn print_debug_stats(&self) {
735734
sty_debug_print!(
736735
self,
737-
TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
738-
TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
736+
TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
737+
TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
739738

740739
println!("Substs interner: #{}", self.substs_interner.borrow().len());
741740
println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@@ -792,12 +791,11 @@ impl<'tcx> TyCtxt<'tcx> {
792791
/// Create an unsafe fn ty based on a safe fn ty.
793792
pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
794793
assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
795-
let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
794+
self.mk_fn_ptr(ty::BareFnTy {
796795
unsafety: hir::Unsafety::Unsafe,
797796
abi: bare_fn.abi,
798797
sig: bare_fn.sig.clone()
799-
});
800-
self.mk_fn(None, unsafe_fn_ty_a)
798+
})
801799
}
802800

803801
pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
@@ -946,26 +944,14 @@ impl<'tcx> TyCtxt<'tcx> {
946944
self.mk_ty(TyBool)
947945
}
948946

949-
pub fn mk_fn(&self,
950-
opt_def_id: Option<DefId>,
951-
fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
952-
self.mk_ty(TyBareFn(opt_def_id, fty))
953-
}
954-
955-
pub fn mk_ctor_fn(&self,
956-
def_id: DefId,
957-
input_tys: &[Ty<'tcx>],
958-
output: Ty<'tcx>) -> Ty<'tcx> {
959-
let input_args = input_tys.iter().cloned().collect();
960-
self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
961-
unsafety: hir::Unsafety::Normal,
962-
abi: Abi::Rust,
963-
sig: ty::Binder(ty::FnSig {
964-
inputs: input_args,
965-
output: ty::FnConverging(output),
966-
variadic: false
967-
})
968-
}))
947+
pub fn mk_fn_def(&self, def_id: DefId,
948+
substs: &'tcx Substs<'tcx>,
949+
fty: BareFnTy<'tcx>) -> Ty<'tcx> {
950+
self.mk_ty(TyFnDef(def_id, substs, self.mk_bare_fn(fty)))
951+
}
952+
953+
pub fn mk_fn_ptr(&self, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
954+
self.mk_ty(TyFnPtr(self.mk_bare_fn(fty)))
969955
}
970956

971957
pub fn mk_trait(&self,

src/librustc/middle/ty/error.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ impl<'tcx> ty::TyS<'tcx> {
223223
ty::TySlice(_) => "slice".to_string(),
224224
ty::TyRawPtr(_) => "*-ptr".to_string(),
225225
ty::TyRef(_, _) => "&-ptr".to_string(),
226-
ty::TyBareFn(Some(_), _) => format!("fn item"),
227-
ty::TyBareFn(None, _) => "fn pointer".to_string(),
226+
ty::TyFnDef(..) => format!("fn item"),
227+
ty::TyFnPtr(_) => "fn pointer".to_string(),
228228
ty::TyTrait(ref inner) => {
229229
format!("trait {}", cx.item_path_str(inner.principal_def_id()))
230230
}

src/librustc/middle/ty/fast_reject.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ pub fn simplify_type(tcx: &TyCtxt,
8383
ty::TyTuple(ref tys) => {
8484
Some(TupleSimplifiedType(tys.len()))
8585
}
86-
ty::TyBareFn(_, ref f) => {
86+
ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
8787
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
8888
}
8989
ty::TyProjection(_) | ty::TyParam(_) => {

src/librustc/middle/ty/flags.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,12 @@ impl FlagComputation {
134134
self.add_tys(&ts[..]);
135135
}
136136

137-
&ty::TyBareFn(_, ref f) => {
137+
&ty::TyFnDef(_, substs, ref f) => {
138+
self.add_substs(substs);
139+
self.add_fn_sig(&f.sig);
140+
}
141+
142+
&ty::TyFnPtr(ref f) => {
138143
self.add_fn_sig(&f.sig);
139144
}
140145
}

src/librustc/middle/ty/outlives.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
182182
ty::TyRawPtr(..) | // ...
183183
ty::TyRef(..) | // OutlivesReference
184184
ty::TyTuple(..) | // ...
185-
ty::TyBareFn(..) | // OutlivesFunction (*)
185+
ty::TyFnDef(..) | // OutlivesFunction (*)
186+
ty::TyFnPtr(_) | // OutlivesFunction (*)
186187
ty::TyTrait(..) | // OutlivesObject, OutlivesFragment (*)
187188
ty::TyError => {
188189
// (*) Bare functions and traits are both binders. In the

0 commit comments

Comments
 (0)