Skip to content

Commit dce604a

Browse files
committed
Auto merge of #44295 - plietar:extern-types, r=arielb1
Implement RFC 1861: Extern types A few notes : - Type parameters are not supported. This was an unresolved question from the RFC. It is not clear how useful this feature is, and how variance should be treated. This can be added in a future PR. - `size_of_val` / `align_of_val` can be called with extern types, and respectively return 0 and 1. This differs from the RFC, which specified that they should panic, but after discussion with @eddyb on IRC this seems like a better solution. If/when a `DynSized` trait is added, this will be disallowed statically. - Auto traits are not implemented by default, since the contents of extern types is unknown. This means extern types are `!Sync`, `!Send` and `!Freeze`. This seems like the correct behaviour to me. Manual `unsafe impl Sync for Foo` is still possible. - This PR allows extern type to be used as the tail of a struct, as described by the RFC : ```rust extern { type OpaqueTail; } #[repr(C)] struct FfiStruct { data: u8, more_data: u32, tail: OpaqueTail, } ``` However this is undesirable, as the alignment of `tail` is unknown (the current PR assumes an alignment of 1). Unfortunately we can't prevent it in the general case as the tail could be a type parameter : ```rust #[repr(C)] struct FfiStruct<T: ?Sized> { data: u8, more_data: u32, tail: T, } ``` Adding a `DynSized` trait would solve this as well, by requiring tail fields to be bound by it. - Despite being unsized, pointers to extern types are thin and can be casted from/to integers. However it is not possible to write a `null<T>() -> *const T` function which works with extern types, as I've explained here : #43467 (comment) - Trait objects cannot be built from extern types. I intend to support it eventually, although how this interacts with `DynSized`/`size_of_val` is still unclear. - The definition of `c_void` is unmodified
2 parents 7da9a5e + 1e9e319 commit dce604a

Some content is hidden

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

82 files changed

+732
-114
lines changed

src/librustc/hir/def.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub enum Def {
3535
Variant(DefId),
3636
Trait(DefId),
3737
TyAlias(DefId),
38+
TyForeign(DefId),
3839
AssociatedTy(DefId),
3940
PrimTy(hir::PrimTy),
4041
TyParam(DefId),
@@ -152,7 +153,7 @@ impl Def {
152153
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
153154
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
154155
Def::AssociatedConst(id) | Def::Macro(id, ..) |
155-
Def::GlobalAsm(id) => {
156+
Def::GlobalAsm(id) | Def::TyForeign(id) => {
156157
id
157158
}
158159

@@ -186,6 +187,7 @@ impl Def {
186187
Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
187188
Def::Union(..) => "union",
188189
Def::Trait(..) => "trait",
190+
Def::TyForeign(..) => "foreign type",
189191
Def::Method(..) => "method",
190192
Def::Const(..) => "constant",
191193
Def::AssociatedConst(..) => "associated constant",

src/librustc/hir/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
704704
}
705705
}
706706
ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
707+
ForeignItemType => (),
707708
}
708709

709710
walk_list!(visitor, visit_attribute, &foreign_item.attrs);

src/librustc/hir/lowering.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,9 @@ impl<'a> LoweringContext<'a> {
17221722
ForeignItemKind::Static(ref t, m) => {
17231723
hir::ForeignItemStatic(this.lower_ty(t), m)
17241724
}
1725+
ForeignItemKind::Ty => {
1726+
hir::ForeignItemType
1727+
}
17251728
},
17261729
vis: this.lower_visibility(&i.vis, None),
17271730
span: i.span,

src/librustc/hir/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1912,13 +1912,16 @@ pub enum ForeignItem_ {
19121912
/// A foreign static item (`static ext: u8`), with optional mutability
19131913
/// (the boolean is true when mutable)
19141914
ForeignItemStatic(P<Ty>, bool),
1915+
/// A foreign type
1916+
ForeignItemType,
19151917
}
19161918

19171919
impl ForeignItem_ {
19181920
pub fn descriptive_variant(&self) -> &str {
19191921
match *self {
19201922
ForeignItemFn(..) => "foreign function",
19211923
ForeignItemStatic(..) => "foreign static item",
1924+
ForeignItemType => "foreign type",
19221925
}
19231926
}
19241927
}

src/librustc/hir/print.rs

+7
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,13 @@ impl<'a> State<'a> {
478478
self.end()?; // end the head-ibox
479479
self.end() // end the outer cbox
480480
}
481+
hir::ForeignItemType => {
482+
self.head(&visibility_qualified(&item.vis, "type"))?;
483+
self.print_name(item.name)?;
484+
self.s.word(";")?;
485+
self.end()?; // end the head-ibox
486+
self.end() // end the outer cbox
487+
}
481488
}
482489
}
483490

src/librustc/ich/impls_hir.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,8 @@ impl_stable_hash_for!(struct hir::ForeignItem {
977977

978978
impl_stable_hash_for!(enum hir::ForeignItem_ {
979979
ForeignItemFn(fn_decl, arg_names, generics),
980-
ForeignItemStatic(ty, is_mutbl)
980+
ForeignItemStatic(ty, is_mutbl),
981+
ForeignItemType
981982
});
982983

983984
impl_stable_hash_for!(enum hir::Stmt_ {
@@ -1086,6 +1087,7 @@ impl_stable_hash_for!(enum hir::def::Def {
10861087
PrimTy(prim_ty),
10871088
TyParam(def_id),
10881089
SelfTy(trait_def_id, impl_def_id),
1090+
TyForeign(def_id),
10891091
Fn(def_id),
10901092
Const(def_id),
10911093
Static(def_id, is_mutbl),

src/librustc/ich/impls_ty.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -610,8 +610,7 @@ for ty::TypeVariants<'gcx>
610610
def_id.hash_stable(hcx, hasher);
611611
closure_substs.hash_stable(hcx, hasher);
612612
}
613-
TyGenerator(def_id, closure_substs, interior)
614-
=> {
613+
TyGenerator(def_id, closure_substs, interior) => {
615614
def_id.hash_stable(hcx, hasher);
616615
closure_substs.hash_stable(hcx, hasher);
617616
interior.hash_stable(hcx, hasher);
@@ -630,6 +629,9 @@ for ty::TypeVariants<'gcx>
630629
TyParam(param_ty) => {
631630
param_ty.hash_stable(hcx, hasher);
632631
}
632+
TyForeign(def_id) => {
633+
def_id.hash_stable(hcx, hasher);
634+
}
633635
TyInfer(..) => {
634636
bug!("ty::TypeVariants::hash_stable() - Unexpected variant {:?}.", *self)
635637
}

src/librustc/infer/freshen.rs

+1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
312312
ty::TyNever |
313313
ty::TyTuple(..) |
314314
ty::TyProjection(..) |
315+
ty::TyForeign(..) |
315316
ty::TyParam(..) |
316317
ty::TyAnon(..) => {
317318
t.super_fold_with(self)

src/librustc/middle/resolve_lifetime.rs

+3
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
365365
hir::ForeignItemStatic(..) => {
366366
intravisit::walk_foreign_item(self, item);
367367
}
368+
hir::ForeignItemType => {
369+
intravisit::walk_foreign_item(self, item);
370+
}
368371
}
369372
}
370373

src/librustc/traits/coherence.rs

+4
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal)-> bool {
304304
def.did.is_local()
305305
}
306306

307+
ty::TyForeign(did) => {
308+
did.is_local()
309+
}
310+
307311
ty::TyDynamic(ref tt, ..) => {
308312
tt.principal().map_or(false, |p| p.def_id().is_local())
309313
}

src/librustc/traits/error_reporting.rs

+1
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
255255
AdtKind::Enum => Some(17),
256256
},
257257
ty::TyGenerator(..) => Some(18),
258+
ty::TyForeign(..) => Some(19),
258259
ty::TyInfer(..) | ty::TyError => None
259260
}
260261
}

src/librustc/traits/select.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17051705
// say nothing; a candidate may be added by
17061706
// `assemble_candidates_from_object_ty`.
17071707
}
1708+
ty::TyForeign(..) => {
1709+
// Since the contents of foreign types is unknown,
1710+
// we don't add any `..` impl. Default traits could
1711+
// still be provided by a manual implementation for
1712+
// this trait and type.
1713+
}
17081714
ty::TyParam(..) |
17091715
ty::TyProjection(..) => {
17101716
// In these cases, we don't know what the actual
@@ -2022,7 +2028,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20222028
Where(ty::Binder(Vec::new()))
20232029
}
20242030

2025-
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,
2031+
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never,
20262032

20272033
ty::TyTuple(tys, _) => {
20282034
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
@@ -2066,7 +2072,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
20662072
Where(ty::Binder(Vec::new()))
20672073
}
20682074

2069-
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | ty::TyGenerator(..) |
2075+
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
2076+
ty::TyGenerator(..) | ty::TyForeign(..) |
20702077
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
20712078
Never
20722079
}
@@ -2148,6 +2155,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
21482155

21492156
ty::TyDynamic(..) |
21502157
ty::TyParam(..) |
2158+
ty::TyForeign(..) |
21512159
ty::TyProjection(..) |
21522160
ty::TyInfer(ty::TyVar(_)) |
21532161
ty::TyInfer(ty::FreshTy(_)) |

src/librustc/ty/context.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1610,7 +1610,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
16101610
pub fn print_debug_stats(self) {
16111611
sty_debug_print!(
16121612
self,
1613-
TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyGenerator,
1613+
TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyGenerator, TyForeign,
16141614
TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
16151615

16161616
println!("Substs interner: #{}", self.interners.substs.borrow().len());
@@ -1861,6 +1861,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
18611861
self.mk_ty(TyAdt(def, substs))
18621862
}
18631863

1864+
pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
1865+
self.mk_ty(TyForeign(def_id))
1866+
}
1867+
18641868
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
18651869
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
18661870
let adt_def = self.adt_def(def_id);

src/librustc/ty/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
182182
ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
183183

184184
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
185+
ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
185186
ty::TyArray(_, n) => {
186187
if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
187188
format!("array of {} elements", n)

src/librustc/ty/fast_reject.rs

+6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ pub enum SimplifiedTypeGen<D>
4949
AnonSimplifiedType(D),
5050
FunctionSimplifiedType(usize),
5151
ParameterSimplifiedType,
52+
ForeignSimplifiedType(DefId),
5253
}
5354

5455
/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc.
@@ -113,6 +114,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
113114
ty::TyAnon(def_id, _) => {
114115
Some(AnonSimplifiedType(def_id))
115116
}
117+
ty::TyForeign(def_id) => {
118+
Some(ForeignSimplifiedType(def_id))
119+
}
116120
ty::TyInfer(_) | ty::TyError => None,
117121
}
118122
}
@@ -140,6 +144,7 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
140144
AnonSimplifiedType(d) => AnonSimplifiedType(map(d)),
141145
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
142146
ParameterSimplifiedType => ParameterSimplifiedType,
147+
ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
143148
}
144149
}
145150
}
@@ -172,6 +177,7 @@ impl<'gcx, D> HashStable<StableHashingContext<'gcx>> for SimplifiedTypeGen<D>
172177
GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher),
173178
AnonSimplifiedType(d) => d.hash_stable(hcx, hasher),
174179
FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher),
180+
ForeignSimplifiedType(d) => d.hash_stable(hcx, hasher),
175181
}
176182
}
177183
}

src/librustc/ty/flags.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ impl FlagComputation {
6363
&ty::TyFloat(_) |
6464
&ty::TyUint(_) |
6565
&ty::TyNever |
66-
&ty::TyStr => {
66+
&ty::TyStr |
67+
&ty::TyForeign(..) => {
6768
}
6869

6970
// You might think that we could just return TyError for

src/librustc/ty/item_path.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
281281
}
282282
}
283283

284+
ty::TyForeign(did) => self.push_item_path(buffer, did),
285+
284286
ty::TyBool |
285287
ty::TyChar |
286288
ty::TyInt(_) |
@@ -344,8 +346,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
344346
.next(),
345347

346348
ty::TyFnDef(def_id, _) |
347-
ty::TyClosure(def_id, _) => Some(def_id),
348-
ty::TyGenerator(def_id, _, _) => Some(def_id),
349+
ty::TyClosure(def_id, _) |
350+
ty::TyGenerator(def_id, _, _) |
351+
ty::TyForeign(def_id) => Some(def_id),
349352

350353
ty::TyBool |
351354
ty::TyChar |

src/librustc/ty/layout.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1141,14 +1141,15 @@ impl<'a, 'tcx> Layout {
11411141
Ok(Scalar { value: Pointer, non_zero: non_zero })
11421142
} else {
11431143
let unsized_part = tcx.struct_tail(pointee);
1144-
let meta = match unsized_part.sty {
1145-
ty::TySlice(_) | ty::TyStr => {
1146-
Int(dl.ptr_sized_integer())
1147-
}
1148-
ty::TyDynamic(..) => Pointer,
1149-
_ => return Err(LayoutError::Unknown(unsized_part))
1150-
};
1151-
Ok(FatPointer { metadata: meta, non_zero: non_zero })
1144+
match unsized_part.sty {
1145+
ty::TySlice(_) | ty::TyStr => Ok(FatPointer {
1146+
metadata: Int(dl.ptr_sized_integer()),
1147+
non_zero: non_zero
1148+
}),
1149+
ty::TyDynamic(..) => Ok(FatPointer { metadata: Pointer, non_zero: non_zero }),
1150+
ty::TyForeign(..) => Ok(Scalar { value: Pointer, non_zero: non_zero }),
1151+
_ => Err(LayoutError::Unknown(unsized_part)),
1152+
}
11521153
}
11531154
};
11541155

@@ -1239,7 +1240,7 @@ impl<'a, 'tcx> Layout {
12391240
non_zero: false
12401241
}
12411242
}
1242-
ty::TyDynamic(..) => {
1243+
ty::TyDynamic(..) | ty::TyForeign(..) => {
12431244
let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
12441245
StructKind::AlwaysSizedUnivariant, ty)?;
12451246
unit.sized = false;
@@ -2252,7 +2253,8 @@ impl<'a, 'tcx> TyLayout<'tcx> {
22522253
ty::TyFnPtr(_) |
22532254
ty::TyNever |
22542255
ty::TyFnDef(..) |
2255-
ty::TyDynamic(..) => {
2256+
ty::TyDynamic(..) |
2257+
ty::TyForeign(..) => {
22562258
bug!("TyLayout::field_type({:?}): not applicable", self)
22572259
}
22582260

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
17841784
vec![]
17851785
}
17861786

1787-
TyStr | TyDynamic(..) | TySlice(_) | TyError => {
1787+
TyStr | TyDynamic(..) | TySlice(_) | TyForeign(..) | TyError => {
17881788
// these are never sized - return the target type
17891789
vec![ty]
17901790
}

src/librustc/ty/outlives.rs

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
142142
ty::TyNever | // ...
143143
ty::TyAdt(..) | // OutlivesNominalType
144144
ty::TyAnon(..) | // OutlivesNominalType (ish)
145+
ty::TyForeign(..) | // OutlivesNominalType
145146
ty::TyStr | // OutlivesScalar (ish)
146147
ty::TyArray(..) | // ...
147148
ty::TySlice(..) | // ...

src/librustc/ty/relate.rs

+6
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,12 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
381381
Ok(tcx.mk_adt(a_def, substs))
382382
}
383383

384+
(&ty::TyForeign(a_id), &ty::TyForeign(b_id))
385+
if a_id == b_id =>
386+
{
387+
Ok(tcx.mk_foreign(a_id))
388+
}
389+
384390
(&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => {
385391
let region_bound = relation.with_cause(Cause::ExistentialRegionBound,
386392
|relation| {

src/librustc/ty/structural_impls.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
676676
ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
677677
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
678678
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
679-
ty::TyParam(..) | ty::TyNever => return self
679+
ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => return self
680680
};
681681

682682
if self.sty == sty {
@@ -710,7 +710,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
710710
ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
711711
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
712712
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
713-
ty::TyParam(..) | ty::TyNever => false,
713+
ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => false,
714714
}
715715
}
716716

0 commit comments

Comments
 (0)