diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 3dc0ee2b55530..461b4c79a1d1c 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -24,7 +24,6 @@ use crate::intrinsics;
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
-/// [`unreachable!`]: ../macro.unreachable.html
///
/// # Example
///
@@ -61,7 +60,7 @@ pub const unsafe fn unreachable_unchecked() -> ! {
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
-/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
+/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 9bcacd8ddcf77..960cccc0fb211 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -6,9 +6,12 @@
//! as moving an object with pointers to itself will invalidate them, which could cause undefined
//! behavior.
//!
-//! A [`Pin
`] ensures that the pointee of any pointer type `P` has a stable location in memory,
-//! meaning it cannot be moved elsewhere and its memory cannot be deallocated
-//! until it gets dropped. We say that the pointee is "pinned".
+//! At a high level, a [`Pin
`] ensures that the pointee of any pointer type
+//! `P` has a stable location in memory, meaning it cannot be moved elsewhere
+//! and its memory cannot be deallocated until it gets dropped. We say that the
+//! pointee is "pinned". Things get more subtle when discussing types that
+//! combine pinned with non-pinned data; [see below](#projections-and-structural-pinning)
+//! for more details.
//!
//! By default, all types in Rust are movable. Rust allows passing all types by-value,
//! and common smart-pointer types such as [`Box`] and `&mut T` allow replacing and
@@ -61,6 +64,10 @@
//!
//! # Example: self-referential struct
//!
+//! Before we go into more details to explain the guarantees and choices
+//! associated with `Pin`, we discuss some examples for how it might be used.
+//! Feel free to [skip to where the theoretical discussion continues](#drop-guarantee).
+//!
//! ```rust
//! use std::pin::Pin;
//! use std::marker::PhantomPinned;
diff --git a/library/std/src/sys/windows/ext/ffi.rs b/library/std/src/sys/windows/ext/ffi.rs
index 6e78119383f43..1df2a0df143b3 100644
--- a/library/std/src/sys/windows/ext/ffi.rs
+++ b/library/std/src/sys/windows/ext/ffi.rs
@@ -30,13 +30,13 @@
//! [`OsString`] is the Rust wrapper for owned strings in the
//! preferred representation of the operating system. On Windows,
//! this struct gets augmented with an implementation of the
-//! [`OsStringExt`] trait, which has a [`from_wide`] method. This
+//! [`OsStringExt`] trait, which has a [`OsStringExt::from_wide`] method. This
//! lets you create an [`OsString`] from a `&[u16]` slice; presumably
//! you get such a slice out of a `WCHAR` Windows API.
//!
//! Similarly, [`OsStr`] is the Rust wrapper for borrowed strings from
//! preferred representation of the operating system. On Windows, the
-//! [`OsStrExt`] trait provides the [`encode_wide`] method, which
+//! [`OsStrExt`] trait provides the [`OsStrExt::encode_wide`] method, which
//! outputs an [`EncodeWide`] iterator. You can [`collect`] this
//! iterator, for example, to obtain a `Vec`; you can later get a
//! pointer to this vector's contents and feed it to Windows APIs.
@@ -47,15 +47,8 @@
//! ill-formed UTF-16.
//!
//! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16
-//! [`OsString`]: ../../../ffi/struct.OsString.html
-//! [`OsStr`]: ../../../ffi/struct.OsStr.html
-//! [`OsStringExt`]: trait.OsStringExt.html
-//! [`OsStrExt`]: trait.OsStrExt.html
-//! [`EncodeWide`]: struct.EncodeWide.html
-//! [`from_wide`]: trait.OsStringExt.html#tymethod.from_wide
-//! [`encode_wide`]: trait.OsStrExt.html#tymethod.encode_wide
-//! [`collect`]: ../../../iter/trait.Iterator.html#method.collect
-//! [U+FFFD]: ../../../char/constant.REPLACEMENT_CHARACTER.html
+//! [`collect`]: crate::iter::Iterator::collect
+//! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
#![stable(feature = "rust1", since = "1.0.0")]
@@ -68,14 +61,12 @@ use crate::sys_common::{AsInner, FromInner};
pub use crate::sys_common::wtf8::EncodeWide;
/// Windows-specific extensions to [`OsString`].
-///
-/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait OsStringExt {
/// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
/// 16-bit code units.
///
- /// This is lossless: calling [`encode_wide`] on the resulting string
+ /// This is lossless: calling [`OsStrExt::encode_wide`] on the resulting string
/// will always return the original code units.
///
/// # Examples
@@ -89,8 +80,6 @@ pub trait OsStringExt {
///
/// let string = OsString::from_wide(&source[..]);
/// ```
- ///
- /// [`encode_wide`]: ./trait.OsStrExt.html#tymethod.encode_wide
#[stable(feature = "rust1", since = "1.0.0")]
fn from_wide(wide: &[u16]) -> Self;
}
@@ -103,14 +92,12 @@ impl OsStringExt for OsString {
}
/// Windows-specific extensions to [`OsStr`].
-///
-/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait OsStrExt {
/// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially
/// ill-formed UTF-16.
///
- /// This is lossless: calling [`OsString::from_wide`] and then
+ /// This is lossless: calling [`OsStringExt::from_wide`] and then
/// `encode_wide` on the result will yield the original code units.
/// Note that the encoding does not add a final null terminator.
///
@@ -128,8 +115,6 @@ pub trait OsStrExt {
/// let result: Vec = string.encode_wide().collect();
/// assert_eq!(&source[..], &result[..]);
/// ```
- ///
- /// [`OsString::from_wide`]: ./trait.OsStringExt.html#tymethod.from_wide
#[stable(feature = "rust1", since = "1.0.0")]
fn encode_wide(&self) -> EncodeWide<'_>;
}
diff --git a/library/std/src/sys/windows/ext/fs.rs b/library/std/src/sys/windows/ext/fs.rs
index 81b2bf9987200..e0615f2d33431 100644
--- a/library/std/src/sys/windows/ext/fs.rs
+++ b/library/std/src/sys/windows/ext/fs.rs
@@ -8,9 +8,7 @@ use crate::path::Path;
use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut};
-/// Windows-specific extensions to [`File`].
-///
-/// [`File`]: ../../../fs/struct.File.html
+/// Windows-specific extensions to [`fs::File`].
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
/// Seeks to a given position and reads a number of bytes.
@@ -94,8 +92,6 @@ impl FileExt for fs::File {
}
/// Windows-specific extensions to [`fs::OpenOptions`].
-///
-/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
#[stable(feature = "open_options_ext", since = "1.10.0")]
pub trait OpenOptionsExt {
/// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
@@ -295,7 +291,6 @@ impl OpenOptionsExt for OpenOptions {
/// The data members that this trait exposes correspond to the members
/// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
///
-/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`BY_HANDLE_FILE_INFORMATION`]:
/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information
#[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -499,11 +494,9 @@ impl MetadataExt for Metadata {
}
}
-/// Windows-specific extensions to [`FileType`].
+/// Windows-specific extensions to [`fs::FileType`].
///
/// On Windows, a symbolic link knows whether it is a file or directory.
-///
-/// [`FileType`]: ../../../../std/fs/struct.FileType.html
#[unstable(feature = "windows_file_type_ext", issue = "none")]
pub trait FileTypeExt {
/// Returns `true` if this file type is a symbolic link that is also a directory.
diff --git a/library/std/src/sys/windows/ext/process.rs b/library/std/src/sys/windows/ext/process.rs
index 8c34a9faf1d4a..61e4c6a1d1718 100644
--- a/library/std/src/sys/windows/ext/process.rs
+++ b/library/std/src/sys/windows/ext/process.rs
@@ -73,8 +73,6 @@ impl IntoRawHandle for process::ChildStderr {
}
/// Windows-specific extensions to [`process::ExitStatus`].
-///
-/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
#[stable(feature = "exit_status_from", since = "1.12.0")]
pub trait ExitStatusExt {
/// Creates a new `ExitStatus` from the raw underlying `u32` return value of
@@ -91,8 +89,6 @@ impl ExitStatusExt for process::ExitStatus {
}
/// Windows-specific extensions to the [`process::Command`] builder.
-///
-/// [`process::Command`]: ../../../../std/process/struct.Command.html
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
pub trait CommandExt {
/// Sets the [process creation flags][1] to be passed to `CreateProcess`.
diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh
index 1be80741594cc..9f6a7f2e5db44 100644
--- a/src/ci/docker/scripts/emscripten.sh
+++ b/src/ci/docker/scripts/emscripten.sh
@@ -19,5 +19,5 @@ exit 1
git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable
cd /emsdk-portable
-hide_output ./emsdk install 1.38.46-upstream
-./emsdk activate 1.38.46-upstream
+hide_output ./emsdk install 1.38.47-upstream
+./emsdk activate 1.38.47-upstream
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 5186e62fbf9bc..699f5c9778a2f 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -5,7 +5,7 @@ use crate::Arena;
use rustc_ast::ast::*;
use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
@@ -75,6 +75,18 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
}
}
+ fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) {
+ match fk {
+ FnKind::Fn(FnCtxt::Foreign, _, sig, _, _) => {
+ self.visit_fn_header(&sig.header);
+ visit::walk_fn_decl(self, &sig.decl);
+ // Don't visit the foreign function body even if it has one, since lowering the
+ // body would have no meaning and will have already been caught as a parse error.
+ }
+ _ => visit::walk_fn(self, fk, sp),
+ }
+ }
+
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
AssocCtxt::Trait => {
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 87d7f00c703a5..51cc1ada432dc 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -61,7 +61,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
let mut reachable_non_generics: DefIdMap<_> = tcx
.reachable_set(LOCAL_CRATE)
.iter()
- .filter_map(|&hir_id| {
+ .filter_map(|&def_id| {
// We want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// categories:
@@ -75,9 +75,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
- match tcx.hir().get(hir_id) {
+ match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
Node::ForeignItem(..) => {
- let def_id = tcx.hir().local_def_id(hir_id);
tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
}
@@ -87,7 +86,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
..
})
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
- let def_id = tcx.hir().local_def_id(hir_id);
let generics = tcx.generics_of(def_id);
if !generics.requires_monomorphization(tcx)
// Functions marked with #[inline] are codegened with "internal"
@@ -361,7 +359,7 @@ fn upstream_drop_glue_for_provider<'tcx>(
fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
if let Some(def_id) = def_id.as_local() {
- !tcx.reachable_set(LOCAL_CRATE).contains(&tcx.hir().local_def_id_to_hir_id(def_id))
+ !tcx.reachable_set(LOCAL_CRATE).contains(&def_id)
} else {
bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
}
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index d364a46463821..d874edf627472 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -740,7 +740,8 @@ rustc_queries! {
}
Other {
- query reachable_set(_: CrateNum) -> &'tcx HirIdSet {
+ query reachable_set(_: CrateNum) -> FxHashSet {
+ storage(ArenaCacheSelector<'tcx>)
desc { "reachability" }
}
diff --git a/src/librustc_middle/ty/consts/kind.rs b/src/librustc_middle/ty/consts/kind.rs
index a4c177160f5d0..ede28522000af 100644
--- a/src/librustc_middle/ty/consts/kind.rs
+++ b/src/librustc_middle/ty/consts/kind.rs
@@ -34,7 +34,7 @@ pub enum ConstKind<'tcx> {
/// A placeholder for a const which could not be computed; this is
/// propagated to avoid useless error messages.
- Error(ty::sty::DelaySpanBugEmitted),
+ Error(ty::DelaySpanBugEmitted),
}
#[cfg(target_arch = "x86_64")]
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 784815f27201f..d7eeaafbf46bf 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -65,6 +65,12 @@ use std::mem;
use std::ops::{Bound, Deref};
use std::sync::Arc;
+/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
+/// except through `tcx.err*()`, which are in this module.
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
+pub struct DelaySpanBugEmitted(());
+
type InternedSet<'tcx, T> = ShardedHashMap, ()>;
pub struct CtxtInterners<'tcx> {
@@ -1171,7 +1177,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[track_caller]
pub fn ty_error_with_message>(self, span: S, msg: &str) -> Ty<'tcx> {
self.sess.delay_span_bug(span, msg);
- self.mk_ty(Error(super::sty::DelaySpanBugEmitted(())))
+ self.mk_ty(Error(DelaySpanBugEmitted(())))
}
/// Like `err` but for constants.
@@ -1179,10 +1185,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
self.sess
.delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported.");
- self.mk_const(ty::Const {
- val: ty::ConstKind::Error(super::sty::DelaySpanBugEmitted(())),
- ty,
- })
+ self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
}
pub fn consider_optimizing String>(&self, msg: T) -> bool {
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 62a62085c6664..3c79fe1225579 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -60,6 +60,7 @@ pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNER
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig};
pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts};
+pub use self::sty::{ClosureSubstsParts, GeneratorSubstsParts};
pub use self::sty::{ConstVid, FloatVid, IntVid, RegionVid, TyVid};
pub use self::sty::{ExistentialPredicate, InferTy, ParamConst, ParamTy, ProjectionTy};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
@@ -72,8 +73,8 @@ pub use self::binding::BindingMode::*;
pub use self::context::{tls, FreeRegionInfo, TyCtxt};
pub use self::context::{
- CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
- UserType, UserTypeAnnotationIndex,
+ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+ DelaySpanBugEmitted, ResolvedOpaqueTy, UserType, UserTypeAnnotationIndex,
};
pub use self::context::{
CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckResults,
diff --git a/src/librustc_middle/ty/query/mod.rs b/src/librustc_middle/ty/query/mod.rs
index b39c0b5190a6d..4d820f75c56c4 100644
--- a/src/librustc_middle/ty/query/mod.rs
+++ b/src/librustc_middle/ty/query/mod.rs
@@ -43,7 +43,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
+use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind;
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 05cd1ae456b35..82160681ee8cf 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -10,7 +10,7 @@ use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::{
self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
};
-use crate::ty::{List, ParamEnv, TyS};
+use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
use polonius_engine::Atom;
use rustc_ast::ast;
use rustc_data_structures::captures::Captures;
@@ -212,12 +212,6 @@ impl TyKind<'tcx> {
}
}
-/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
-/// except through `tcx.err*()`.
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
-#[derive(TyEncodable, TyDecodable, HashStable)]
-pub struct DelaySpanBugEmitted(pub(super) ());
-
// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(TyKind<'_>, 24);
@@ -325,24 +319,39 @@ pub struct ClosureSubsts<'tcx> {
pub substs: SubstsRef<'tcx>,
}
-/// Struct returned by `split()`. Note that these are subslices of the
-/// parent slice and not canonical substs themselves.
-struct SplitClosureSubsts<'tcx> {
- parent: &'tcx [GenericArg<'tcx>],
- closure_kind_ty: GenericArg<'tcx>,
- closure_sig_as_fn_ptr_ty: GenericArg<'tcx>,
- tupled_upvars_ty: GenericArg<'tcx>,
+/// Struct returned by `split()`.
+pub struct ClosureSubstsParts<'tcx, T> {
+ pub parent_substs: &'tcx [GenericArg<'tcx>],
+ pub closure_kind_ty: T,
+ pub closure_sig_as_fn_ptr_ty: T,
+ pub tupled_upvars_ty: T,
}
impl<'tcx> ClosureSubsts<'tcx> {
- /// Divides the closure substs into their respective
- /// components. Single source of truth with respect to the
- /// ordering.
- fn split(self) -> SplitClosureSubsts<'tcx> {
+ /// Construct `ClosureSubsts` from `ClosureSubstsParts`, containing `Substs`
+ /// for the closure parent, alongside additional closure-specific components.
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ parts: ClosureSubstsParts<'tcx, Ty<'tcx>>,
+ ) -> ClosureSubsts<'tcx> {
+ ClosureSubsts {
+ substs: tcx.mk_substs(
+ parts.parent_substs.iter().copied().chain(
+ [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty]
+ .iter()
+ .map(|&ty| ty.into()),
+ ),
+ ),
+ }
+ }
+
+ /// Divides the closure substs into their respective components.
+ /// The ordering assumed here must match that used by `ClosureSubsts::new` above.
+ fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> {
match self.substs[..] {
- [ref parent @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
- SplitClosureSubsts {
- parent,
+ [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
+ ClosureSubstsParts {
+ parent_substs,
closure_kind_ty,
closure_sig_as_fn_ptr_ty,
tupled_upvars_ty,
@@ -363,7 +372,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
/// Returns the substitutions of the closure's parent.
pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
- self.split().parent
+ self.split().parent_substs
}
#[inline]
@@ -418,21 +427,46 @@ pub struct GeneratorSubsts<'tcx> {
pub substs: SubstsRef<'tcx>,
}
-struct SplitGeneratorSubsts<'tcx> {
- parent: &'tcx [GenericArg<'tcx>],
- resume_ty: GenericArg<'tcx>,
- yield_ty: GenericArg<'tcx>,
- return_ty: GenericArg<'tcx>,
- witness: GenericArg<'tcx>,
- tupled_upvars_ty: GenericArg<'tcx>,
+pub struct GeneratorSubstsParts<'tcx, T> {
+ pub parent_substs: &'tcx [GenericArg<'tcx>],
+ pub resume_ty: T,
+ pub yield_ty: T,
+ pub return_ty: T,
+ pub witness: T,
+ pub tupled_upvars_ty: T,
}
impl<'tcx> GeneratorSubsts<'tcx> {
- fn split(self) -> SplitGeneratorSubsts<'tcx> {
+ /// Construct `GeneratorSubsts` from `GeneratorSubstsParts`, containing `Substs`
+ /// for the generator parent, alongside additional generator-specific components.
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>,
+ ) -> GeneratorSubsts<'tcx> {
+ GeneratorSubsts {
+ substs: tcx.mk_substs(
+ parts.parent_substs.iter().copied().chain(
+ [
+ parts.resume_ty,
+ parts.yield_ty,
+ parts.return_ty,
+ parts.witness,
+ parts.tupled_upvars_ty,
+ ]
+ .iter()
+ .map(|&ty| ty.into()),
+ ),
+ ),
+ }
+ }
+
+ /// Divides the generator substs into their respective components.
+ /// The ordering assumed here must match that used by `GeneratorSubsts::new` above.
+ fn split(self) -> GeneratorSubstsParts<'tcx, GenericArg<'tcx>> {
match self.substs[..] {
- [ref parent @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
- SplitGeneratorSubsts {
- parent,
+ [ref parent_substs @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
+ GeneratorSubstsParts {
+ parent_substs,
resume_ty,
yield_ty,
return_ty,
@@ -455,7 +489,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
/// Returns the substitutions of the generator's parent.
pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
- self.split().parent
+ self.split().parent_substs
}
/// This describes the types that can be contained in a generator.
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index 18fa4ada4dadd..8d5c980609cd9 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -12,11 +12,11 @@ use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirIdSet, Node};
+use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::middle::privacy;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::config::CrateType;
use rustc_target::spec::abi::Abi;
@@ -65,10 +65,11 @@ struct ReachableContext<'tcx> {
tcx: TyCtxt<'tcx>,
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
// The set of items which must be exported in the linkage sense.
- reachable_symbols: HirIdSet,
+ reachable_symbols: FxHashSet,
// A worklist of item IDs. Each item ID in this worklist will be inlined
// and will be scanned for further references.
- worklist: Vec,
+ // FIXME(eddyb) benchmark if this would be faster as a `VecDeque`.
+ worklist: Vec,
// Whether any output of this compilation is a library
any_library: bool,
}
@@ -100,37 +101,27 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
_ => None,
};
- match res {
- Some(Res::Local(hir_id)) => {
- self.reachable_symbols.insert(hir_id);
- }
- Some(res) => {
- if let Some((hir_id, def_id)) = res.opt_def_id().and_then(|def_id| {
- def_id
- .as_local()
- .map(|def_id| (self.tcx.hir().local_def_id_to_hir_id(def_id), def_id))
- }) {
- if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
- self.worklist.push(hir_id);
- } else {
- match res {
- // If this path leads to a constant, then we need to
- // recurse into the constant to continue finding
- // items that are reachable.
- Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
- self.worklist.push(hir_id);
- }
+ if let Some(res) = res {
+ if let Some(def_id) = res.opt_def_id().and_then(|def_id| def_id.as_local()) {
+ if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
+ self.worklist.push(def_id);
+ } else {
+ match res {
+ // If this path leads to a constant, then we need to
+ // recurse into the constant to continue finding
+ // items that are reachable.
+ Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
+ self.worklist.push(def_id);
+ }
- // If this wasn't a static, then the destination is
- // surely reachable.
- _ => {
- self.reachable_symbols.insert(hir_id);
- }
+ // If this wasn't a static, then the destination is
+ // surely reachable.
+ _ => {
+ self.reachable_symbols.insert(def_id);
}
}
}
}
- _ => {}
}
intravisit::walk_expr(self, expr)
@@ -209,13 +200,15 @@ impl<'tcx> ReachableContext<'tcx> {
continue;
}
- if let Some(ref item) = self.tcx.hir().find(search_item) {
+ if let Some(ref item) =
+ self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(search_item))
+ {
self.propagate_node(item, search_item);
}
}
}
- fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
+ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
if !self.any_library {
// If we are building an executable, only explicitly extern
// types need to be exported.
@@ -297,8 +290,9 @@ impl<'tcx> ReachableContext<'tcx> {
self.visit_nested_body(body);
}
hir::ImplItemKind::Fn(_, body) => {
- let did = self.tcx.hir().get_parent_did(search_item);
- if method_might_be_inlined(self.tcx, impl_item, did) {
+ let impl_def_id =
+ self.tcx.parent(search_item.to_def_id()).unwrap().expect_local();
+ if method_might_be_inlined(self.tcx, impl_item, impl_def_id) {
self.visit_nested_body(body)
}
}
@@ -317,7 +311,9 @@ impl<'tcx> ReachableContext<'tcx> {
_ => {
bug!(
"found unexpected node kind in worklist: {} ({:?})",
- self.tcx.hir().node_to_string(search_item),
+ self.tcx
+ .hir()
+ .node_to_string(self.tcx.hir().local_def_id_to_hir_id(search_item)),
node,
);
}
@@ -336,7 +332,7 @@ impl<'tcx> ReachableContext<'tcx> {
struct CollectPrivateImplItemsVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
access_levels: &'a privacy::AccessLevels,
- worklist: &'a mut Vec,
+ worklist: &'a mut Vec,
}
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> {
@@ -349,13 +345,16 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
if codegen_attrs.contains_extern_indicator()
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
{
- self.worklist.push(item.hir_id);
+ self.worklist.push(def_id);
}
// We need only trait impls here, not inherent impls, and only non-exported ones
if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind {
if !self.access_levels.is_reachable(item.hir_id) {
- self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.hir_id));
+ // FIXME(#53488) remove `let`
+ let tcx = self.tcx;
+ self.worklist
+ .extend(items.iter().map(|ii_ref| tcx.hir().local_def_id(ii_ref.id.hir_id)));
let trait_def_id = match trait_ref.path.res {
Res::Def(DefKind::Trait, def_id) => def_id,
@@ -366,12 +365,10 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
return;
}
- // FIXME(#53488) remove `let`
- let tcx = self.tcx;
- self.worklist
- .extend(tcx.provided_trait_methods(trait_def_id).map(|assoc| {
- tcx.hir().local_def_id_to_hir_id(assoc.def_id.expect_local())
- }));
+ self.worklist.extend(
+ tcx.provided_trait_methods(trait_def_id)
+ .map(|assoc| assoc.def_id.expect_local()),
+ );
}
}
}
@@ -383,7 +380,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx
}
}
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet {
+fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet {
debug_assert!(crate_num == LOCAL_CRATE);
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
@@ -405,11 +402,13 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet
// If other crates link to us, they're going to expect to be able to
// use the lang items, so we need to be sure to mark them as
// exported.
- reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id));
+ reachable_context
+ .worklist
+ .extend(access_levels.map.iter().map(|(id, _)| tcx.hir().local_def_id(*id)));
for item in tcx.lang_items().items().iter() {
- if let Some(did) = *item {
- if let Some(hir_id) = did.as_local().map(|did| tcx.hir().local_def_id_to_hir_id(did)) {
- reachable_context.worklist.push(hir_id);
+ if let Some(def_id) = *item {
+ if let Some(def_id) = def_id.as_local() {
+ reachable_context.worklist.push(def_id);
}
}
}
@@ -428,7 +427,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet
debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols);
// Return the set of reachable symbols.
- tcx.arena.alloc(reachable_context.reachable_symbols)
+ reachable_context.reachable_symbols
}
pub fn provide(providers: &mut Providers) {
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 66dbe53bac387..f10f9b2ce93c5 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -437,6 +437,7 @@ impl Session {
}
}
/// Delay a span_bug() call until abort_if_errors()
+ #[track_caller]
pub fn delay_span_bug>(&self, sp: S, msg: &str) {
self.diagnostic().delay_span_bug(sp, msg)
}
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 255f611cfa357..c7f9e9d63e03c 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -11,7 +11,7 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, GenericParamDefKind, Ty};
+use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
@@ -76,60 +76,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let generator_types =
check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1;
- let base_substs = InternalSubsts::identity_for_item(
+ let parent_substs = InternalSubsts::identity_for_item(
self.tcx,
self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
);
- // HACK(eddyb) this hardcodes indices into substs but it should rely on
- // `ClosureSubsts` and `GeneratorSubsts` providing constructors, instead.
- // That would also remove the need for most of the inference variables,
- // as they immediately unified with the actual type below, including
- // the `InferCtxt::closure_sig` and `ClosureSubsts::sig_ty` methods.
- let tupled_upvars_idx = base_substs.len() + if generator_types.is_some() { 4 } else { 2 };
- let substs =
- base_substs.extend_to(self.tcx, expr_def_id.to_def_id(), |param, _| match param.kind {
- GenericParamDefKind::Lifetime => span_bug!(expr.span, "closure has lifetime param"),
- GenericParamDefKind::Type { .. } => if param.index as usize == tupled_upvars_idx {
- self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(
- |upvars| {
- upvars.iter().map(|(&var_hir_id, _)| {
- // Create type variables (for now) to represent the transformed
- // types of upvars. These will be unified during the upvar
- // inference phase (`upvar.rs`).
- self.infcx.next_ty_var(TypeVariableOrigin {
- // FIXME(eddyb) distinguish upvar inference variables from the rest.
- kind: TypeVariableOriginKind::ClosureSynthetic,
- span: self.tcx.hir().span(var_hir_id),
- })
- })
- },
- ))
- } else {
- // Create type variables (for now) to represent the various
- // pieces of information kept in `{Closure,Generic}Substs`.
- // They will either be unified below, or later during the upvar
- // inference phase (`upvar.rs`)
+
+ let tupled_upvars_ty =
+ self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(|upvars| {
+ upvars.iter().map(|(&var_hir_id, _)| {
+ // Create type variables (for now) to represent the transformed
+ // types of upvars. These will be unified during the upvar
+ // inference phase (`upvar.rs`).
self.infcx.next_ty_var(TypeVariableOrigin {
+ // FIXME(eddyb) distinguish upvar inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
- span: expr.span,
+ span: self.tcx.hir().span(var_hir_id),
})
- }
- .into(),
- GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
- });
+ })
+ }));
+
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
- let generator_substs = substs.as_generator();
- self.demand_eqtype(expr.span, resume_ty, generator_substs.resume_ty());
- self.demand_eqtype(expr.span, yield_ty, generator_substs.yield_ty());
- self.demand_eqtype(expr.span, liberated_sig.output(), generator_substs.return_ty());
- self.demand_eqtype(expr.span, interior, generator_substs.witness());
-
- // HACK(eddyb) this forces the types equated above into `substs` but
- // it should rely on `GeneratorSubsts` providing a constructor, instead.
- let substs = self.resolve_vars_if_possible(&substs);
+ let generator_substs = ty::GeneratorSubsts::new(
+ self.tcx,
+ ty::GeneratorSubstsParts {
+ parent_substs,
+ resume_ty,
+ yield_ty,
+ return_ty: liberated_sig.output(),
+ witness: interior,
+ tupled_upvars_ty,
+ },
+ );
- return self.tcx.mk_generator(expr_def_id.to_def_id(), substs, movability);
+ return self.tcx.mk_generator(
+ expr_def_id.to_def_id(),
+ generator_substs.substs,
+ movability,
+ );
}
// Tuple up the arguments and insert the resulting function type into
@@ -149,18 +133,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr_def_id, sig, opt_kind
);
- let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig);
- self.demand_eqtype(expr.span, sig_fn_ptr_ty, substs.as_closure().sig_as_fn_ptr_ty());
+ let closure_kind_ty = match opt_kind {
+ Some(kind) => kind.to_ty(self.tcx),
- if let Some(kind) = opt_kind {
- self.demand_eqtype(expr.span, kind.to_ty(self.tcx), substs.as_closure().kind_ty());
- }
+ // Create a type variable (for now) to represent the closure kind.
+ // It will be unified during the upvar inference phase (`upvar.rs`)
+ None => self.infcx.next_ty_var(TypeVariableOrigin {
+ // FIXME(eddyb) distinguish closure kind inference variables from the rest.
+ kind: TypeVariableOriginKind::ClosureSynthetic,
+ span: expr.span,
+ }),
+ };
- // HACK(eddyb) this forces the types equated above into `substs` but
- // it should rely on `ClosureSubsts` providing a constructor, instead.
- let substs = self.resolve_vars_if_possible(&substs);
+ let closure_substs = ty::ClosureSubsts::new(
+ self.tcx,
+ ty::ClosureSubstsParts {
+ parent_substs,
+ closure_kind_ty,
+ closure_sig_as_fn_ptr_ty: self.tcx.mk_fn_ptr(sig),
+ tupled_upvars_ty,
+ },
+ );
- let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), substs);
+ let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs);
debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type);
diff --git a/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs b/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs
new file mode 100644
index 0000000000000..a84065e021868
--- /dev/null
+++ b/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs
@@ -0,0 +1,11 @@
+// Previously this ICE'd because `fn g()` would be lowered, but the block associated with `fn f()`
+// wasn't.
+
+// compile-flags: --crate-type=lib
+
+extern "C" {
+ fn f() {
+ //~^ incorrect function inside `extern` block
+ fn g() {}
+ }
+}
diff --git a/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr b/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr
new file mode 100644
index 0000000000000..d4a9ca3e7c66e
--- /dev/null
+++ b/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr
@@ -0,0 +1,19 @@
+error: incorrect function inside `extern` block
+ --> $DIR/issue-74120-lowering-of-ffi-block-bodies.rs:7:8
+ |
+LL | extern "C" {
+ | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL | fn f() {
+ | ________^___-
+ | | |
+ | | cannot have a body
+LL | |
+LL | | fn g() {}
+LL | | }
+ | |_____- help: remove the invalid body: `;`
+ |
+ = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+ = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-66768.rs b/src/test/ui/issues/issue-66768.rs
new file mode 100644
index 0000000000000..ce42c8b01cc32
--- /dev/null
+++ b/src/test/ui/issues/issue-66768.rs
@@ -0,0 +1,205 @@
+// Regression test for #66768.
+// check-pass
+#![allow(dead_code)]
+//-^ "dead code" is needed to reproduce the issue.
+
+use std::marker::PhantomData;
+use std::ops::{Add, Mul};
+
+fn problematic_function(material_surface_element: Edge2dElement)
+where
+ DefaultAllocator: FiniteElementAllocator,
+{
+ let _: Point2 = material_surface_element.map_reference_coords().into();
+}
+
+impl ArrayLength for UTerm {
+ type ArrayType = ();
+}
+impl> ArrayLength for UInt {
+ type ArrayType = GenericArrayImplEven;
+}
+impl> ArrayLength for UInt {
+ type ArrayType = GenericArrayImplOdd;
+}
+impl Add for UTerm {
+ type Output = U;
+ fn add(self, _: U) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl Add> for UInt
+where
+ Ul: Add,
+{
+ type Output = UInt, B1>;
+ fn add(self, _: UInt) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl Mul for UTerm {
+ type Output = UTerm;
+ fn mul(self, _: U) -> Self {
+ unimplemented!()
+ }
+}
+impl Mul> for UInt
+where
+ Ul: Mul>,
+{
+ type Output = UInt>, B0>;
+ fn mul(self, _: UInt) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl Mul> for UInt
+where
+ Ul: Mul>,
+ UInt>, B0>: Add>,
+{
+ type Output = Sum>, B0>, UInt>;
+ fn mul(self, _: UInt) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl Allocator for DefaultAllocator
+where
+ R: DimName,
+ C: DimName,
+ R::Value: Mul,
+ Prod: ArrayLength,
+{
+ type Buffer = ArrayStorage;
+ fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
+ unimplemented!()
+ }
+ fn allocate_from_iterator(_: R, _: C, _: I) -> Self::Buffer {
+ unimplemented!()
+ }
+}
+impl Allocator for DefaultAllocator {
+ type Buffer = VecStorage;
+ fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer {
+ unimplemented!()
+ }
+ fn allocate_from_iterator(_: Dynamic, _: C, _: I) -> Self::Buffer {
+ unimplemented!()
+ }
+}
+impl DimName for DimU1 {
+ type Value = U1;
+ fn name() -> Self {
+ unimplemented!()
+ }
+}
+impl DimName for DimU2 {
+ type Value = U2;
+ fn name() -> Self {
+ unimplemented!()
+ }
+}
+impl From> for Point
+where
+ DefaultAllocator: Allocator,
+{
+ fn from(_: VectorN) -> Self {
+ unimplemented!()
+ }
+}
+impl FiniteElementAllocator for DefaultAllocator where
+ DefaultAllocator: Allocator + Allocator
+{
+}
+impl ReferenceFiniteElement for Edge2dElement {
+ type NodalDim = DimU1;
+}
+impl FiniteElement for Edge2dElement {
+ fn map_reference_coords(&self) -> Vector2 {
+ unimplemented!()
+ }
+}
+
+type Owned = >::Buffer;
+type MatrixMN = Matrix>;
+type VectorN = MatrixMN;
+type Vector2 = VectorN;
+type Point2 = Point;
+type U1 = UInt;
+type U2 = UInt, B0>;
+type Sum = >::Output;
+type Prod = >::Output;
+
+struct GenericArray> {
+ _data: U::ArrayType,
+}
+struct GenericArrayImplEven {
+ _parent2: U,
+ _marker: T,
+}
+struct GenericArrayImplOdd {
+ _parent2: U,
+ _data: T,
+}
+struct B0;
+struct B1;
+struct UTerm;
+struct UInt {
+ _marker: PhantomData<(U, B)>,
+}
+struct DefaultAllocator;
+struct Dynamic;
+struct DimU1;
+struct DimU2;
+struct Matrix {
+ _data: S,
+ _phantoms: PhantomData<(N, R, C)>,
+}
+struct ArrayStorage
+where
+ R: DimName,
+ C: DimName,
+ R::Value: Mul,
+ Prod: ArrayLength,
+{
+ _data: GenericArray>,
+}
+struct VecStorage {
+ _data: N,
+ _nrows: R,
+ _ncols: C,
+}
+struct Point
+where
+ DefaultAllocator: Allocator,
+{
+ _coords: VectorN,
+}
+struct Edge2dElement;
+
+trait ArrayLength {
+ type ArrayType;
+}
+trait Allocator {
+ type Buffer;
+ fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer;
+ fn allocate_from_iterator(nrows: R, ncols: C, iter: I) -> Self::Buffer;
+}
+trait DimName {
+ type Value;
+ fn name() -> Self;
+}
+trait FiniteElementAllocator:
+ Allocator + Allocator
+{
+}
+trait ReferenceFiniteElement {
+ type NodalDim;
+}
+trait FiniteElement: ReferenceFiniteElement
+where
+ DefaultAllocator: FiniteElementAllocator,
+{
+ fn map_reference_coords(&self) -> VectorN;
+}
+
+fn main() {}