Auto merge of #73369 - RalfJung:rollup-hl8g9zf, r=RalfJung

Rollup of 10 pull requests

Successful merges:

 - #72707 (Use min_specialization in the remaining rustc crates)
 - #72740 (On recursive ADT, provide indirection structured suggestion)
 - #72879 (Miri: avoid tracking current location three times)
 - #72938 (Stabilize Option::zip)
 - #73086 (Rename "cyclone" to "apple-a7" per changes in upstream LLVM)
 - #73104 (Example about explicit mutex dropping)
 - #73139 (Add methods to go from a nul-terminated Vec<u8> to a CString)
 - #73296 (Remove vestigial CI job msvc-aux.)
 - #73304 (Revert heterogeneous SocketAddr PartialEq impls)
 - #73331 (extend network support for HermitCore)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-06-15 11:39:23 +00:00
commit ff4a2533a0
92 changed files with 1064 additions and 585 deletions

View file

@ -428,11 +428,6 @@ jobs:
NO_DEBUG_ASSERTIONS: 1
NO_LLVM_ASSERTIONS: 1
os: windows-latest-xl
- name: x86_64-msvc-aux
env:
RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc"
os: windows-latest-xl
- name: x86_64-msvc-cargo
env:
SCRIPT: python x.py test src/tools/cargotest src/tools/cargo

View file

@ -1434,9 +1434,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.1.13"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
dependencies = [
"compiler_builtins",
"libc",

View file

@ -373,7 +373,6 @@ impl<'a> Builder<'a> {
test::UiFullDeps,
test::Rustdoc,
test::Pretty,
test::RunPassValgrindPretty,
test::Crate,
test::CrateLibrustc,
test::CrateRustdoc,

View file

@ -6,12 +6,6 @@ Q := @
BOOTSTRAP_ARGS :=
endif
ifdef EXCLUDE_CARGO
AUX_ARGS :=
else
AUX_ARGS := src/tools/cargo src/tools/cargotest
endif
BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
all:
@ -48,8 +42,8 @@ check:
$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
check-aux:
$(Q)$(BOOTSTRAP) test \
src/test/run-pass-valgrind/pretty \
$(AUX_ARGS) \
src/tools/cargo \
src/tools/cargotest \
$(BOOTSTRAP_ARGS)
check-bootstrap:
$(Q)$(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap_test.py

View file

@ -930,13 +930,6 @@ host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-ful
host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" });
host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" });
test!(RunPassValgrindPretty {
path: "src/test/run-pass-valgrind/pretty",
mode: "pretty",
suite: "run-pass-valgrind",
default: false,
host: true
});
default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" });

View file

@ -142,10 +142,6 @@ jobs:
# FIXME(#59637)
NO_DEBUG_ASSERTIONS: 1
NO_LLVM_ASSERTIONS: 1
# MSVC aux tests
x86_64-msvc-aux:
RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
x86_64-msvc-cargo:
SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld

View file

@ -492,12 +492,6 @@ jobs:
NO_LLVM_ASSERTIONS: 1
<<: *job-windows-xl
- name: x86_64-msvc-aux
env:
RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
<<: *job-windows-xl
- name: x86_64-msvc-cargo
env:
SCRIPT: python x.py test src/tools/cargotest src/tools/cargo

View file

@ -145,7 +145,6 @@
#![feature(associated_type_bounds)]
#![feature(const_type_id)]
#![feature(const_caller_location)]
#![feature(option_zip)]
#![feature(no_niche)] // rust-lang/rust#68303
#[prelude_import]

View file

@ -926,7 +926,6 @@ impl<T> Option<T> {
/// # Examples
///
/// ```
/// #![feature(option_zip)]
/// let x = Some(1);
/// let y = Some("hi");
/// let z = None::<u8>;
@ -934,9 +933,12 @@ impl<T> Option<T> {
/// assert_eq!(x.zip(y), Some((1, "hi")));
/// assert_eq!(x.zip(z), None);
/// ```
#[unstable(feature = "option_zip", issue = "70086")]
#[stable(feature = "option_zip_option", since = "1.46.0")]
pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> {
self.zip_with(other, |a, b| (a, b))
match (self, other) {
(Some(a), Some(b)) => Some((a, b)),
_ => None,
}
}
/// Zips `self` and another `Option` with function `f`.

View file

@ -602,7 +602,7 @@ macro_rules! which_arena_for_type {
#[macro_export]
macro_rules! declare_arena {
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
#[derive(Default)]
pub struct Arena<$tcx> {
pub dropless: $crate::DroplessArena,
@ -611,17 +611,17 @@ macro_rules! declare_arena {
}
#[marker]
pub trait ArenaAllocatable {}
pub trait ArenaAllocatable<'tcx> {}
impl<T: Copy> ArenaAllocatable for T {}
impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {}
unsafe trait ArenaField<'tcx>: Sized {
unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> {
/// Returns a specific arena to allocate from.
/// If `None` is returned, the `DropArena` will be used.
fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>>;
}
unsafe impl<'tcx, T> ArenaField<'tcx> for T {
unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T {
#[inline]
default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>> {
panic!()
@ -630,18 +630,27 @@ macro_rules! declare_arena {
$(
#[allow(unused_lifetimes)]
impl<$tcx> ArenaAllocatable for $ty {}
unsafe impl<$tcx> ArenaField<$tcx> for $ty {
impl<$tcx> ArenaAllocatable<$tcx> for $ty {}
unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> {
#[inline]
fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena<Self>> {
$crate::which_arena_for_type!($a[&_arena.$name])
// SAFETY: We only implement `ArenaAllocatable<$tcx>` for
// `$ty`, so `$ty` and Self are the same type
unsafe {
::std::mem::transmute::<
Option<&'a $crate::TypedArena<$ty>>,
Option<&'a $crate::TypedArena<Self>>,
>(
$crate::which_arena_for_type!($a[&_arena.$name])
)
}
}
}
)*
impl<'tcx> Arena<'tcx> {
#[inline]
pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
if !::std::mem::needs_drop::<T>() {
return self.dropless.alloc(value);
}
@ -659,7 +668,7 @@ macro_rules! declare_arena {
self.dropless.alloc_slice(value)
}
pub fn alloc_from_iter<'a, T: ArenaAllocatable>(
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>(
&'a self,
iter: impl ::std::iter::IntoIterator<Item = T>,
) -> &'a mut [T] {

View file

@ -33,7 +33,7 @@
#![feature(array_value_iter)]
#![feature(crate_visibility_modifier)]
#![feature(marker_trait_attr)]
#![feature(specialization)] // FIXME: min_specialization does not work
#![feature(min_specialization)]
#![feature(or_patterns)]
#![recursion_limit = "256"]

View file

@ -296,6 +296,29 @@ impl Diagnostic {
self
}
pub fn multipart_suggestions(
&mut self,
msg: &str,
suggestions: Vec<Vec<(Span, String)>>,
applicability: Applicability,
) -> &mut Self {
self.suggestions.push(CodeSuggestion {
substitutions: suggestions
.into_iter()
.map(|suggestion| Substitution {
parts: suggestion
.into_iter()
.map(|(span, snippet)| SubstitutionPart { snippet, span })
.collect(),
})
.collect(),
msg: msg.to_owned(),
style: SuggestionStyle::ShowCode,
applicability,
});
self
}
/// Prints out a message with for a multipart suggestion without showing the suggested code.
///
/// This is intended to be used for suggestions that are obvious in what the changes need to

View file

@ -260,6 +260,19 @@ impl<'a> DiagnosticBuilder<'a> {
self
}
pub fn multipart_suggestions(
&mut self,
msg: &str,
suggestions: Vec<Vec<(Span, String)>>,
applicability: Applicability,
) -> &mut Self {
if !self.0.allow_suggestions {
return self;
}
self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability);
self
}
pub fn tool_only_multipart_suggestion(
&mut self,
msg: &str,

View file

@ -12,41 +12,41 @@ macro_rules! arena_types {
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
// HIR types
[few] hir_krate: rustc_hir::Crate<$tcx>,
[] arm: rustc_hir::Arm<$tcx>,
[] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
[] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
[] attribute: rustc_ast::ast::Attribute,
[] block: rustc_hir::Block<$tcx>,
[] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
[few] global_asm: rustc_hir::GlobalAsm,
[] generic_arg: rustc_hir::GenericArg<$tcx>,
[] generic_args: rustc_hir::GenericArgs<$tcx>,
[] generic_bound: rustc_hir::GenericBound<$tcx>,
[] generic_param: rustc_hir::GenericParam<$tcx>,
[] expr: rustc_hir::Expr<$tcx>,
[] field: rustc_hir::Field<$tcx>,
[] field_pat: rustc_hir::FieldPat<$tcx>,
[] fn_decl: rustc_hir::FnDecl<$tcx>,
[] foreign_item: rustc_hir::ForeignItem<$tcx>,
[] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
[] local: rustc_hir::Local<$tcx>,
[few] macro_def: rustc_hir::MacroDef<$tcx>,
[] param: rustc_hir::Param<$tcx>,
[] pat: rustc_hir::Pat<$tcx>,
[] path: rustc_hir::Path<$tcx>,
[] path_segment: rustc_hir::PathSegment<$tcx>,
[] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
[] qpath: rustc_hir::QPath<$tcx>,
[] stmt: rustc_hir::Stmt<$tcx>,
[] struct_field: rustc_hir::StructField<$tcx>,
[] trait_item_ref: rustc_hir::TraitItemRef,
[] ty: rustc_hir::Ty<$tcx>,
[] type_binding: rustc_hir::TypeBinding<$tcx>,
[] variant: rustc_hir::Variant<$tcx>,
[] where_predicate: rustc_hir::WherePredicate<$tcx>,
[few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>;
[] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>;
[] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>;
[] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
[] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
[] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>;
[] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>;
[few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm;
[] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>;
[] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>;
[] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>;
[] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>;
[] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>;
[] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>;
[] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>;
[] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>;
[] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>;
[] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>;
[few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>;
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>;
[] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>;
[few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>;
[] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>;
[] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>;
[] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>;
[] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>;
[] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>;
[] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>;
[] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>;
[] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>;
[] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef;
[] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>;
[] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>;
[] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>;
[] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>;
], $tcx);
)
}

View file

@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
) -> Fallible<CanonicalizedQueryResponse<'tcx, T>>
where
T: Debug + TypeFoldable<'tcx>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
{
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
let canonical_result = self.canonicalize_response(&query_response);

View file

@ -433,7 +433,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
try_load_from_on_disk_cache_stream.extend(quote! {
::rustc_middle::dep_graph::DepKind::#name => {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
debug_assert!($tcx.dep_graph
.node_color($dep_node)
.map(|c| c.is_green())
@ -490,7 +490,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
// Add a match arm to force the query given the dep node
dep_node_force_stream.extend(quote! {
::rustc_middle::dep_graph::DepKind::#name => {
if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
if let Some(key) = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node) {
force_query::<crate::ty::query::queries::#name<'_>, _>(
$tcx,

View file

@ -7,7 +7,7 @@
#![feature(nll)]
#![feature(or_patterns)]
#![feature(proc_macro_internals)]
#![feature(specialization)] // FIXME: min_specialization ICEs
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]
#![recursion_limit = "256"]

View file

@ -30,7 +30,7 @@ use rustc_middle::mir::{self, interpret, Body, Promoted};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util::common::record_time;
use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
use rustc_session::Session;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol};
@ -218,7 +218,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
}
}
impl<'a, 'tcx, T: Decodable> Lazy<T> {
impl<'a, 'tcx, T: Decodable> Lazy<T, ()> {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position);
@ -226,7 +226,7 @@ impl<'a, 'tcx, T: Decodable> Lazy<T> {
}
}
impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> {
fn decode<M: Metadata<'a, 'tcx>>(
self,
metadata: M,
@ -321,20 +321,20 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
}
}
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T, ()>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
self.read_lazy_with_meta(())
}
}
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T], usize>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
let len = self.read_usize()?;
if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) }
}
}
impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>>> for DecodeContext<'a, 'tcx>
impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>, usize>> for DecodeContext<'a, 'tcx>
where
Option<T>: FixedSizeEncoding,
{
@ -515,8 +515,9 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
}
}
impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for DecodeContext<'a, 'tcx>
impl<'a, 'tcx, T> SpecializedDecoder<mir::ClearCrossCrate<T>> for DecodeContext<'a, 'tcx>
where
mir::ClearCrossCrate<T>: UseSpecializedDecodable,
{
#[inline]
fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {

View file

@ -27,7 +27,7 @@ use rustc_middle::mir::{self, interpret};
use rustc_middle::traits::specialization_graph;
use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
use rustc_session::config::CrateType;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident, Symbol};
@ -93,13 +93,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> {
}
}
impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
impl<'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
self.emit_lazy_distance(*lazy)
}
}
impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
impl<'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
self.emit_usize(lazy.meta)?;
if lazy.meta == 0 {
@ -109,7 +109,7 @@ impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
}
}
impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>>> for EncodeContext<'tcx>
impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'tcx>
where
Option<T>: FixedSizeEncoding,
{
@ -228,8 +228,13 @@ impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
}
}
impl<'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
impl<'a, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx>
where
&'a ty::TyS<'b>: UseSpecializedEncodable,
{
fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
debug_assert!(self.tcx.lift(ty).is_some());
let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
}
}
@ -251,12 +256,19 @@ impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
}
}
impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> {
impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> {
fn specialized_encode(
&mut self,
predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
predicates: &&'a [(ty::Predicate<'b>, Span)],
) -> Result<(), Self::Error> {
ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
debug_assert!(self.tcx.lift(*predicates).is_some());
let predicates = unsafe {
std::mem::transmute::<
&&'a [(ty::Predicate<'b>, Span)],
&&'tcx [(ty::Predicate<'tcx>, Span)],
>(predicates)
};
ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands)
}
}
@ -266,7 +278,10 @@ impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
}
}
impl<'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx> {
impl<'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx>
where
mir::ClearCrossCrate<T>: UseSpecializedEncodable,
{
fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
Ok(())
}

View file

@ -11,79 +11,109 @@
macro_rules! arena_types {
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
[] layouts: rustc_target::abi::Layout,
[] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout;
// AdtDef are interned and compared by address
[] adt_def: rustc_middle::ty::AdtDef,
[decode] tables: rustc_middle::ty::TypeckTables<$tcx>,
[] const_allocs: rustc_middle::mir::interpret::Allocation,
[] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef;
[decode] tables: rustc_middle::ty::TypeckTables<$tcx>, rustc_middle::ty::TypeckTables<'_x>;
[] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation;
// Required for the incremental on-disk cache
[few, decode] mir_keys: rustc_hir::def_id::DefIdSet,
[] region_scope_tree: rustc_middle::middle::region::ScopeTree,
[few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet;
[] region_scope_tree: rustc_middle::middle::region::ScopeTree, rustc_middle::middle::region::ScopeTree;
[] dropck_outlives:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx,
rustc_middle::traits::query::DropckOutlivesResult<'tcx>
>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y,
rustc_middle::traits::query::DropckOutlivesResult<'_z>
>
>;
[] normalize_projection_ty:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx,
rustc_middle::traits::query::NormalizationResult<'tcx>
>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y,
rustc_middle::traits::query::NormalizationResult<'_z>
>
>;
[] implied_outlives_bounds:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx,
Vec<rustc_middle::traits::query::OutlivesBound<'tcx>>
>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y,
Vec<rustc_middle::traits::query::OutlivesBound<'_z>>
>
>;
[] type_op_subtype:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, ()>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y, ()>
>;
[] type_op_normalize_poly_fn_sig:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::PolyFnSig<'_z>>
>;
[] type_op_normalize_fn_sig:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::FnSig<'_z>>
>;
[] type_op_normalize_predicate:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
>,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::Predicate<'_z>>
>;
[] type_op_normalize_ty:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
>,
[few] all_traits: Vec<rustc_hir::def_id::DefId>,
[few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
[few] foreign_module: rustc_middle::middle::cstore::ForeignModule,
[few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>,
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
[] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
[] attribute: rustc_ast::ast::Attribute,
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
[] hir_id_set: rustc_hir::HirIdSet,
rustc_middle::infer::canonical::Canonical<'_x,
rustc_middle::infer::canonical::QueryResponse<'_y, &'_z rustc_middle::ty::TyS<'_w>>
>;
[few] all_traits: Vec<rustc_hir::def_id::DefId>, Vec<rustc_hir::def_id::DefId>;
[few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, rustc_middle::middle::privacy::AccessLevels;
[few] foreign_module: rustc_middle::middle::cstore::ForeignModule, rustc_middle::middle::cstore::ForeignModule;
[few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>, Vec<rustc_middle::middle::cstore::ForeignModule>;
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>;
[] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation;
[] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>;
[] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>;
[] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet;
// Interned types
[] tys: rustc_middle::ty::TyS<$tcx>,
[] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>;
// HIR query types
[few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>,
[few] hir_definitions: rustc_hir::definitions::Definitions,
[] hir_owner: rustc_middle::hir::Owner<$tcx>,
[] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
[few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>;
[few] hir_definitions: rustc_hir::definitions::Definitions, rustc_hir::definitions::Definitions;
[] hir_owner: rustc_middle::hir::Owner<$tcx>, rustc_middle::hir::Owner<'_x>;
[] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, rustc_middle::hir::OwnerNodes<'_x>;
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
// since we need to allocate this type on both the `rustc_hir` arena
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
[decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
[decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
// This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
[decode] span: rustc_span::Span,
[decode] span: rustc_span::Span, rustc_span::Span;
], $tcx);
)
}

View file

@ -128,7 +128,7 @@ macro_rules! define_dep_nodes {
// tuple args
$({
return <$tuple_arg_ty as DepNodeParams<TyCtxt<'_>>>
::CAN_RECONSTRUCT_QUERY_KEY;
::can_reconstruct_query_key();
})*
true
@ -304,7 +304,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
]);
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
#[inline]
fn can_reconstruct_query_key() -> bool {
true
}
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
tcx.def_path_hash(*self).0
@ -320,7 +323,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
}
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
#[inline]
fn can_reconstruct_query_key() -> bool {
true
}
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
self.to_def_id().to_fingerprint(tcx)
@ -336,7 +342,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
}
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
#[inline]
fn can_reconstruct_query_key() -> bool {
true
}
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
@ -353,7 +362,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
}
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
#[inline]
fn can_reconstruct_query_key() -> bool {
false
}
// We actually would not need to specialize the implementation of this
// method but it's faster to combine the hashes than to instantiate a full
@ -375,7 +387,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
}
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
#[inline]
fn can_reconstruct_query_key() -> bool {
false
}
// We actually would not need to specialize the implementation of this
// method but it's faster to combine the hashes than to instantiate a full

View file

@ -42,7 +42,7 @@
#![feature(option_expect_none)]
#![feature(or_patterns)]
#![feature(range_is_empty)]
#![feature(specialization)] // FIXME: min_specialization does not work
#![feature(min_specialization)]
#![feature(track_caller)]
#![feature(trusted_len)]
#![feature(vec_remove_item)]

View file

@ -458,8 +458,39 @@ impl<T> ClearCrossCrate<T> {
}
}
impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {}
impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {}
const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {
#[inline]
fn default_encode<E: rustc_serialize::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
match *self {
ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
ClearCrossCrate::Set(ref val) => {
TAG_CLEAR_CROSS_CRATE_SET.encode(e)?;
val.encode(e)
}
}
}
}
impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {
#[inline]
fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
where
D: rustc_serialize::Decoder,
{
let discr = u8::decode(d)?;
match discr {
TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(ClearCrossCrate::Clear),
TAG_CLEAR_CROSS_CRATE_SET => {
let val = T::decode(d)?;
Ok(ClearCrossCrate::Set(val))
}
_ => unreachable!(),
}
}
}
/// Grouped information about the source code origin of a MIR entity.
/// Intended to be inspected by diagnostics and debuginfo.
@ -1958,8 +1989,6 @@ impl<V, T> ProjectionElem<V, T> {
/// and the index is a local.
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
impl<'tcx> Copy for PlaceElem<'tcx> {}
// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
#[cfg(target_arch = "x86_64")]
static_assert_size!(PlaceElem<'_>, 16);

View file

@ -97,7 +97,7 @@ where
pub fn encode_spanned_predicates<'tcx, E, C>(
encoder: &mut E,
predicates: &'tcx [(ty::Predicate<'tcx>, Span)],
predicates: &[(ty::Predicate<'tcx>, Span)],
cache: C,
) -> Result<(), E::Error>
where
@ -139,7 +139,7 @@ pub trait TyDecoder<'tcx>: Decoder {
}
#[inline]
pub fn decode_arena_allocable<D, T: ArenaAllocatable + Decodable>(
pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
decoder: &mut D,
) -> Result<&'tcx T, D::Error>
where
@ -149,7 +149,7 @@ where
}
#[inline]
pub fn decode_arena_allocable_slice<D, T: ArenaAllocatable + Decodable>(
pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
decoder: &mut D,
) -> Result<&'tcx [T], D::Error>
where
@ -318,18 +318,38 @@ macro_rules! __impl_decoder_methods {
macro_rules! impl_arena_allocatable_decoder {
([]$args:tt) => {};
([decode $(, $attrs:ident)*]
[[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
[[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty, $gen_ty:ty], $tcx:lifetime]) => {
// FIXME(#36588): These impls are horribly unsound as they allow
// the caller to pick any lifetime for `'tcx`, including `'static`.
#[allow(unused_lifetimes)]
impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a $gen_ty>
for $DecoderName<$($typaram),*>
where &'_a $gen_ty: UseSpecializedDecodable
{
#[inline]
fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
decode_arena_allocable(self)
fn specialized_decode(&mut self) -> Result<&'_a $gen_ty, Self::Error> {
unsafe {
std::mem::transmute::<
Result<&$tcx $ty, Self::Error>,
Result<&'_a $gen_ty, Self::Error>,
>(decode_arena_allocable(self))
}
}
}
impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
#[allow(unused_lifetimes)]
impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a [$gen_ty]>
for $DecoderName<$($typaram),*>
where &'_a [$gen_ty]: UseSpecializedDecodable
{
#[inline]
fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
decode_arena_allocable_slice(self)
fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> {
unsafe {
std::mem::transmute::<
Result<&$tcx [$ty], Self::Error>,
Result<&'_a [$gen_ty], Self::Error>,
>(decode_arena_allocable_slice(self))
}
}
}
};
@ -340,9 +360,9 @@ macro_rules! impl_arena_allocatable_decoder {
#[macro_export]
macro_rules! impl_arena_allocatable_decoders {
($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
($args:tt, [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
$(
impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
impl_arena_allocatable_decoder!($a [$args, [$name: $ty, $gen_ty], $tcx]);
)*
}
}
@ -352,14 +372,15 @@ macro_rules! implement_ty_decoder {
($DecoderName:ident <$($typaram:tt),*>) => {
mod __ty_decoder_impl {
use std::borrow::Cow;
use std::mem::transmute;
use rustc_serialize::{Decoder, SpecializedDecoder};
use rustc_serialize::{Decoder, SpecializedDecoder, UseSpecializedDecodable};
use $crate::infer::canonical::CanonicalVarInfos;
use $crate::ty;
use $crate::ty::codec::*;
use $crate::ty::subst::SubstsRef;
use rustc_hir::def_id::{CrateNum};
use $crate::ty::subst::InternalSubsts;
use rustc_hir::def_id::CrateNum;
use rustc_span::Span;
@ -398,8 +419,7 @@ macro_rules! implement_ty_decoder {
}
// FIXME(#36588): These impls are horribly unsound as they allow
// the caller to pick any lifetime for `'tcx`, including `'static`,
// by using the unspecialized proxies to them.
// the caller to pick any lifetime for `'tcx`, including `'static`.
rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
@ -411,90 +431,98 @@ macro_rules! implement_ty_decoder {
}
}
impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
decode_ty(self)
impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::TyS<'_y>>
for $DecoderName<$($typaram),*>
where &'_x ty::TyS<'_y>: UseSpecializedDecodable
{
fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> {
unsafe { transmute::<Result<ty::Ty<'tcx>, Self::Error>, Result<&'_x ty::TyS<'_y>, Self::Error>>(decode_ty(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
for $DecoderName<$($typaram),*> {
impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x [(ty::Predicate<'_y>, Span)]>
for $DecoderName<$($typaram),*>
where &'_x [(ty::Predicate<'_y>, Span)]: UseSpecializedDecodable {
fn specialized_decode(&mut self)
-> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> {
decode_spanned_predicates(self)
-> Result<&'_x [(ty::Predicate<'_y>, Span)], Self::Error>
{
unsafe { transmute(decode_spanned_predicates(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
decode_substs(self)
impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x InternalSubsts<'_y>>
for $DecoderName<$($typaram),*>
where &'_x InternalSubsts<'_y>: UseSpecializedDecodable {
fn specialized_decode(&mut self) -> Result<&'_x InternalSubsts<'_y>, Self::Error> {
unsafe { transmute(decode_substs(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
impl<'_x, $($typaram),*> SpecializedDecoder<$crate::mir::Place<'_x>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(
&mut self
) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
decode_place(self)
) -> Result<$crate::mir::Place<'_x>, Self::Error> {
unsafe { transmute(decode_place(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
impl<'_x, $($typaram),*> SpecializedDecoder<ty::Region<'_x>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
decode_region(self)
fn specialized_decode(&mut self) -> Result<ty::Region<'_x>, Self::Error> {
unsafe { transmute(decode_region(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
for $DecoderName<$($typaram),*> {
impl<'_x, '_y, '_z, $($typaram),*> SpecializedDecoder<&'_x ty::List<&'_y ty::TyS<'_z>>>
for $DecoderName<$($typaram),*>
where &'_x ty::List<&'_y ty::TyS<'_z>>: UseSpecializedDecodable {
fn specialized_decode(&mut self)
-> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
decode_ty_slice(self)
-> Result<&'_x ty::List<&'_y ty::TyS<'_z>>, Self::Error> {
unsafe { transmute(decode_ty_slice(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
impl<'_x, $($typaram),*> SpecializedDecoder<&'_x ty::AdtDef>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
decode_adt_def(self)
fn specialized_decode(&mut self) -> Result<&'_x ty::AdtDef, Self::Error> {
unsafe { transmute(decode_adt_def(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::List<ty::ExistentialPredicate<'_y>>>
for $DecoderName<$($typaram),*>
where &'_x ty::List<ty::ExistentialPredicate<'_y>>: UseSpecializedDecodable {
fn specialized_decode(&mut self)
-> Result<&'_x ty::List<ty::ExistentialPredicate<'_y>>, Self::Error> {
unsafe { transmute(decode_existential_predicate_slice(self)) }
}
}
impl<'_x, $($typaram),*> SpecializedDecoder<CanonicalVarInfos<'_x>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self)
-> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
decode_existential_predicate_slice(self)
-> Result<CanonicalVarInfos<'_x>, Self::Error> {
unsafe { transmute(decode_canonical_var_infos(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self)
-> Result<CanonicalVarInfos<'tcx>, Self::Error> {
decode_canonical_var_infos(self)
impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x $crate::ty::Const<'_y>>
for $DecoderName<$($typaram),*>
where &'_x $crate::ty::Const<'_y>: UseSpecializedDecodable {
fn specialized_decode(&mut self) -> Result<&'_x ty::Const<'_y>, Self::Error> {
unsafe { transmute(decode_const(self)) }
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
decode_const(self)
}
}
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
impl<'_x, $($typaram),*> SpecializedDecoder<&'_x $crate::mir::interpret::Allocation>
for $DecoderName<$($typaram),*> {
fn specialized_decode(
&mut self
) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
decode_allocation(self)
) -> Result<&'_x $crate::mir::interpret::Allocation, Self::Error> {
unsafe { transmute(decode_allocation(self)) }
}
}
}
}
};
}

View file

@ -1,6 +1,6 @@
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use crate::mir::interpret;
use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use crate::mir::{self, interpret};
use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
use crate::ty::context::TyCtxt;
use crate::ty::{self, Ty};
@ -26,9 +26,6 @@ use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
const TAG_NO_EXPN_DATA: u8 = 0;
const TAG_EXPN_DATA_SHORTHAND: u8 = 1;
const TAG_EXPN_DATA_INLINE: u8 = 2;
@ -667,24 +664,6 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx> {
}
}
impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
for CacheDecoder<'a, 'tcx>
{
#[inline]
fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
let discr = u8::decode(self)?;
match discr {
TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(mir::ClearCrossCrate::Clear),
TAG_CLEAR_CROSS_CRATE_SET => {
let val = T::decode(self)?;
Ok(mir::ClearCrossCrate::Set(val))
}
_ => unreachable!(),
}
}
}
//- ENCODING -------------------------------------------------------------------
/// An encoder that can write the incr. comp. cache.
@ -828,17 +807,20 @@ where
}
}
impl<'a, 'tcx, E> SpecializedEncoder<Ty<'tcx>> for CacheEncoder<'a, 'tcx, E>
impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b ty::TyS<'c>> for CacheEncoder<'a, 'tcx, E>
where
E: 'a + TyEncoder,
&'b ty::TyS<'c>: UseSpecializedEncodable,
{
#[inline]
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
fn specialized_encode(&mut self, ty: &&'b ty::TyS<'c>) -> Result<(), Self::Error> {
debug_assert!(self.tcx.lift(ty).is_some());
let ty = unsafe { std::mem::transmute::<&&'b ty::TyS<'c>, &&'tcx ty::TyS<'tcx>>(ty) };
ty_codec::encode_with_shorthand(self, ty, |encoder| &mut encoder.type_shorthands)
}
}
impl<'a, 'tcx, E> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b [(ty::Predicate<'c>, Span)]>
for CacheEncoder<'a, 'tcx, E>
where
E: 'a + TyEncoder,
@ -846,8 +828,15 @@ where
#[inline]
fn specialized_encode(
&mut self,
predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
predicates: &&'b [(ty::Predicate<'c>, Span)],
) -> Result<(), Self::Error> {
debug_assert!(self.tcx.lift(*predicates).is_some());
let predicates = unsafe {
std::mem::transmute::<
&&'b [(ty::Predicate<'c>, Span)],
&&'tcx [(ty::Predicate<'tcx>, Span)],
>(predicates)
};
ty_codec::encode_spanned_predicates(self, predicates, |encoder| {
&mut encoder.predicate_shorthands
})
@ -890,23 +879,6 @@ impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for CacheEncoder<'a, 'tcx, opaque
}
}
impl<'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for CacheEncoder<'a, 'tcx, E>
where
E: 'a + TyEncoder,
T: Encodable,
{
#[inline]
fn specialized_encode(&mut self, val: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
match *val {
mir::ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(self),
mir::ClearCrossCrate::Set(ref val) => {
TAG_CLEAR_CROSS_CRATE_SET.encode(self)?;
val.encode(self)
}
}
}
}
macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => {
#[inline]
@ -995,7 +967,7 @@ fn encode_query_results<'a, 'tcx, Q, E>(
query_result_index: &mut EncodedQueryResultIndex,
) -> Result<(), E::Error>
where
Q: super::QueryDescription<TyCtxt<'tcx>>,
Q: super::QueryDescription<TyCtxt<'tcx>> + super::QueryAccessors<TyCtxt<'tcx>>,
Q::Value: Encodable,
E: 'a + TyEncoder,
{

View file

@ -112,30 +112,53 @@ impl<T: Debug> IntoSelfProfilingString for T {
}
}
impl IntoSelfProfilingString for DefId {
impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
self.spec_to_self_profile_string(builder)
}
}
#[rustc_specialization_trait]
pub trait SpecIntoSelfProfilingString: Debug {
fn spec_to_self_profile_string(
&self,
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
) -> StringId;
}
impl SpecIntoSelfProfilingString for DefId {
fn spec_to_self_profile_string(
&self,
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
) -> StringId {
builder.def_id_to_string_id(*self)
}
}
impl IntoSelfProfilingString for CrateNum {
fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
impl SpecIntoSelfProfilingString for CrateNum {
fn spec_to_self_profile_string(
&self,
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
) -> StringId {
builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
}
}
impl IntoSelfProfilingString for DefIndex {
fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
impl SpecIntoSelfProfilingString for DefIndex {
fn spec_to_self_profile_string(
&self,
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
) -> StringId {
builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
}
}
impl<T0, T1> IntoSelfProfilingString for (T0, T1)
impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
where
T0: IntoSelfProfilingString + Debug,
T1: IntoSelfProfilingString + Debug,
T0: SpecIntoSelfProfilingString,
T1: SpecIntoSelfProfilingString,
{
default fn to_self_profile_string(
fn spec_to_self_profile_string(
&self,
builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
) -> StringId {

View file

@ -1,4 +1,4 @@
use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt};
use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt, TyS};
use rustc_span::symbol::Symbol;
@ -13,9 +13,11 @@ impl<'tcx, T> Value<'tcx> for T {
}
}
impl<'tcx> Value<'tcx> for Ty<'tcx> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
tcx.types.err
impl<'tcx> Value<'tcx> for &'_ TyS<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
// SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.types.err) }
}
}
@ -25,8 +27,14 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
}
}
impl<'tcx> Value<'tcx> for AdtSizedConstraint<'tcx> {
impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err]))
// SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe {
std::mem::transmute::<AdtSizedConstraint<'tcx>, AdtSizedConstraint<'_>>(
AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])),
)
}
}
}

View file

@ -2409,8 +2409,6 @@ impl<'tcx> Const<'tcx> {
}
}
impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
/// Represents a constant in Rust.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
#[derive(HashStable)]

View file

@ -705,6 +705,7 @@ impl<'tcx> ty::TyS<'tcx> {
/// optimization as well as the rules around static values. Note
/// that the `Freeze` trait is not exposed to end users and is
/// effectively an implementation detail.
// FIXME: use `TyCtxtAt` instead of separate `Span`.
pub fn is_freeze(
&'tcx self,
tcx: TyCtxt<'tcx>,
@ -878,7 +879,15 @@ impl<'tcx> ty::TyS<'tcx> {
// Find non representable fields with their spans
fold_repr(def.all_fields().map(|field| {
let ty = field.ty(tcx, substs);
let span = tcx.hir().span_if_local(field.did).unwrap_or(sp);
let span = match field
.did
.as_local()
.map(|id| tcx.hir().as_local_hir_id(id))
.and_then(|id| tcx.hir().find(id))
{
Some(hir::Node::Field(field)) => field.ty.span,
_ => sp,
};
match is_type_structurally_recursive(
tcx,
span,

View file

@ -2,7 +2,7 @@ use std::error::Error;
use std::fmt;
use rustc_middle::mir::AssertKind;
use rustc_span::Symbol;
use rustc_span::{Span, Symbol};
use super::InterpCx;
use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
@ -53,8 +53,9 @@ impl Error for ConstEvalErrKind {}
pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
ecx: &InterpCx<'mir, 'tcx, M>,
error: InterpErrorInfo<'tcx>,
span: Option<Span>,
) -> ConstEvalErr<'tcx> {
error.print_backtrace();
let stacktrace = ecx.generate_stacktrace();
ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) }
}

View file

@ -27,7 +27,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
body: &'mir mir::Body<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
let tcx = ecx.tcx.tcx;
let tcx = *ecx.tcx;
let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
assert!(!layout.is_unsized());
let ret = ecx.allocate(layout, MemoryKind::Stack);
@ -81,13 +81,14 @@ fn eval_body_using_ecx<'mir, 'tcx>(
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
pub(super) fn mk_eval_cx<'mir, 'tcx>(
tcx: TyCtxt<'tcx>,
span: Span,
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
can_access_statics: bool,
) -> CompileTimeEvalContext<'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
InterpCx::new(
tcx.at(span),
tcx,
root_span,
param_env,
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
MemoryExtra { can_access_statics },
@ -163,7 +164,7 @@ pub(super) fn op_to_const<'tcx>(
0,
),
};
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
let len = b.to_machine_usize(ecx).unwrap();
let start = start.try_into().unwrap();
let len: usize = len.try_into().unwrap();
ConstValue::Slice { data, start, end: start + len }
@ -212,7 +213,7 @@ fn validate_and_turn_into_const<'tcx>(
})();
val.map_err(|error| {
let err = error_to_const_error(&ecx, error);
let err = error_to_const_error(&ecx, error, None);
err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
diag.note(note_on_undefined_behavior_error());
diag.emit();
@ -299,9 +300,9 @@ pub fn const_eval_raw_provider<'tcx>(
let is_static = tcx.is_static(def_id);
let span = tcx.def_span(cid.instance.def_id());
let mut ecx = InterpCx::new(
tcx.at(span),
tcx,
tcx.def_span(cid.instance.def_id()),
key.param_env,
CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
MemoryExtra { can_access_statics: is_static },
@ -311,12 +312,15 @@ pub fn const_eval_raw_provider<'tcx>(
res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body))
.map(|place| RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty })
.map_err(|error| {
let err = error_to_const_error(&ecx, error);
let err = error_to_const_error(&ecx, error, None);
// errors in statics are always emitted as fatal errors
if is_static {
// Ensure that if the above error was either `TooGeneric` or `Reported`
// an error must be reported.
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
let v = err.report_as_error(
ecx.tcx.at(ecx.cur_span()),
"could not evaluate static initializer",
);
// If this is `Reveal:All`, then we need to make sure an error is reported but if
// this is `Reveal::UserFacing`, then it's expected that we could get a
@ -372,13 +376,16 @@ pub fn const_eval_raw_provider<'tcx>(
// anything else (array lengths, enum initializers, constant patterns) are
// reported as hard errors
} else {
err.report_as_error(ecx.tcx, "evaluation of constant value failed")
err.report_as_error(
ecx.tcx.at(ecx.cur_span()),
"evaluation of constant value failed",
)
}
}
}
} else {
// use of broken constant from other crate
err.report_as_error(ecx.tcx, "could not evaluate constant")
err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")
}
})
}

View file

@ -268,11 +268,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
(&ty::Array(_, length), &ty::Slice(_)) => {
let ptr = self.read_immediate(src)?.to_scalar()?;
// u64 cast is from usize to u64, which is always good
let val = Immediate::new_slice(
ptr,
length.eval_usize(self.tcx.tcx, self.param_env),
self,
);
let val =
Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
self.write_immediate(val, dest)
}
(&ty::Dynamic(..), &ty::Dynamic(..)) => {

View file

@ -33,6 +33,8 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
pub machine: M,
/// The results of the type checker, from rustc.
/// The span in this is the "root" of the evaluation, i.e., the const
/// we are evaluating (if this is CTFE).
pub tcx: TyCtxtAt<'tcx>,
/// Bounds in scope for polymorphic evaluations.
@ -202,7 +204,7 @@ where
}
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
type Ty = Ty<'tcx>;
type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
@ -285,14 +287,15 @@ pub(super) fn from_known_layout<'tcx>(
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub fn new(
tcx: TyCtxtAt<'tcx>,
tcx: TyCtxt<'tcx>,
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
machine: M,
memory_extra: M::MemoryExtra,
) -> Self {
InterpCx {
machine,
tcx,
tcx: tcx.at(root_span),
param_env,
memory: Memory::new(tcx, memory_extra),
vtables: FxHashMap::default(),
@ -300,9 +303,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
#[inline(always)]
pub fn set_span(&mut self, span: Span) {
self.tcx.span = span;
self.memory.tcx.span = span;
pub fn cur_span(&self) -> Span {
self.stack()
.last()
.and_then(|f| f.current_source_info())
.map(|si| si.span)
.unwrap_or(self.tcx.span)
}
#[inline(always)]
@ -385,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[inline]
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(*self.tcx, self.param_env, DUMMY_SP)
ty.is_freeze(*self.tcx, self.param_env, self.tcx.span)
}
pub fn load_mir(
@ -554,7 +560,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let size = size.align_to(align);
// Check if this brought us over the size limit.
if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
if size.bytes() >= self.tcx.data_layout.obj_size_bound() {
throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
}
Ok(Some((size, align)))
@ -570,7 +576,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let elem = layout.field(self, 0)?;
// Make sure the slice is not too big.
let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
let size = elem.size.checked_mul(len, self).ok_or_else(|| {
err_ub!(InvalidMeta("slice is bigger than largest supported object"))
})?;
Ok(Some((size, elem.align.abi)))

View file

@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
if let InternMode::Static(mutability) = mode {
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
// no interior mutability.
let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx.tcx, ecx.param_env, ecx.tcx.span));
let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env, ecx.tcx.span));
// For statics, allocation mutability is the combination of the place mutability and
// the type mutability.
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@ -253,8 +253,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
// caused (by somehow getting a mutable reference in a `const`).
if ref_mutability == Mutability::Mut {
match referenced_ty.kind {
ty::Array(_, n)
if n.eval_usize(tcx.tcx, self.ecx.param_env) == 0 => {}
ty::Array(_, n) if n.eval_usize(*tcx, self.ecx.param_env) == 0 => {}
ty::Slice(_)
if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)?
== 0 => {}

View file

@ -347,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
let elem = args[2];
let input = args[0];
let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx.tcx);
let (len, e_ty) = input.layout.ty.simd_size_and_type(*self.tcx);
assert!(
index < len,
"Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
@ -374,7 +374,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
sym::simd_extract => {
let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
let (len, e_ty) = args[0].layout.ty.simd_size_and_type(*self.tcx);
assert!(
index < len,
"index `{}` is out-of-bounds of vector type `{}` with length `{}`",

View file

@ -14,7 +14,7 @@ use std::ptr;
use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::ty::{self, query::TyCtxtAt, Instance, ParamEnv};
use rustc_middle::ty::{self, Instance, ParamEnv, TyCtxt};
use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
use super::{
@ -115,7 +115,7 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
pub extra: M::MemoryExtra,
/// Lets us implement `HasDataLayout`, which is awfully convenient.
pub tcx: TyCtxtAt<'tcx>,
pub tcx: TyCtxt<'tcx>,
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> {
@ -126,7 +126,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
}
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self {
Memory {
alloc_map: M::MemoryMap::default(),
extra_fn_ptr_map: FxHashMap::default(),
@ -425,7 +425,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
/// `M::tag_allocation`.
fn get_global_alloc(
memory_extra: &M::MemoryExtra,
tcx: TyCtxtAt<'tcx>,
tcx: TyCtxt<'tcx>,
id: AllocId,
is_write: bool,
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
@ -455,7 +455,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
throw_unsup!(ReadForeignStatic(def_id))
}
trace!("get_global_alloc: Need to compute {:?}", def_id);
let instance = Instance::mono(tcx.tcx, def_id);
let instance = Instance::mono(tcx, def_id);
let gid = GlobalId { instance, promoted: None };
// Use the raw query here to break validation cycles. Later uses of the static
// will call the full query anyway.
@ -664,14 +664,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
// Cannot be a closure because it is generic in `Tag`, `Extra`.
fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
tcx: TyCtxtAt<'tcx>,
tcx: TyCtxt<'tcx>,
allocs_to_print: &mut VecDeque<AllocId>,
alloc: &Allocation<Tag, Extra>,
) {
for &(_, target_id) in alloc.relocations().values() {
allocs_to_print.push_back(target_id);
}
pretty::write_allocation(tcx.tcx, alloc, &mut std::io::stderr()).unwrap();
pretty::write_allocation(tcx, alloc, &mut std::io::stderr()).unwrap();
}
allocs.sort();
@ -820,7 +820,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
return Ok(());
}
};
let tcx = self.tcx.tcx;
let tcx = self.tcx;
self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
}
@ -846,7 +846,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
return Ok(());
}
};
let tcx = self.tcx.tcx;
let tcx = self.tcx;
let allocation = self.get_raw_mut(ptr.alloc_id)?;
for idx in 0..len {
@ -888,7 +888,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
let relocations =
self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length);
let tcx = self.tcx.tcx;
let tcx = self.tcx;
// This checks relocation edges on the src.
let src_bytes =

View file

@ -651,12 +651,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Convert discriminant to variant index, and catch invalid discriminants.
let index = match op.layout.ty.kind {
ty::Adt(adt, _) => {
adt.discriminants(self.tcx.tcx).find(|(_, var)| var.val == discr_bits)
adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
}
ty::Generator(def_id, substs, _) => {
let substs = substs.as_generator();
substs
.discriminants(def_id, self.tcx.tcx)
.discriminants(def_id, *self.tcx)
.find(|(_, var)| var.val == discr_bits)
}
_ => bug!("tagged layout for non-adt non-generator"),

View file

@ -404,7 +404,10 @@ where
// to get some code to work that probably ought to work.
field_layout.align.abi
}
None => bug!("Cannot compute offset for extern type field at non-0 offset"),
None => span_bug!(
self.cur_span(),
"cannot compute offset for extern type field at non-0 offset"
),
};
(base.meta, offset.align_to(align))
} else {
@ -440,7 +443,11 @@ where
assert!(!field_layout.is_unsized());
base.offset(offset, MemPlaceMeta::None, field_layout, self)
}
_ => bug!("`mplace_index` called on non-array type {:?}", base.layout.ty),
_ => span_bug!(
self.cur_span(),
"`mplace_index` called on non-array type {:?}",
base.layout.ty
),
}
}
@ -454,7 +461,7 @@ where
let len = base.len(self)?; // also asserts that we have a type where this makes sense
let stride = match base.layout.fields {
FieldsShape::Array { stride, .. } => stride,
_ => bug!("mplace_array_fields: expected an array layout"),
_ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"),
};
let layout = base.layout.field(self, 0)?;
let dl = &self.tcx.data_layout;
@ -484,7 +491,9 @@ where
// (that have count 0 in their layout).
let from_offset = match base.layout.fields {
FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked
_ => bug!("Unexpected layout of index access: {:#?}", base.layout),
_ => {
span_bug!(self.cur_span(), "unexpected layout of index access: {:#?}", base.layout)
}
};
// Compute meta and new layout
@ -497,7 +506,9 @@ where
let len = Scalar::from_machine_usize(inner_len, self);
(MemPlaceMeta::Meta(len), base.layout.ty)
}
_ => bug!("cannot subslice non-array type: `{:?}`", base.layout.ty),
_ => {
span_bug!(self.cur_span(), "cannot subslice non-array type: `{:?}`", base.layout.ty)
}
};
let layout = self.layout_of(ty)?;
base.offset(from_offset, meta, layout, self)
@ -768,7 +779,7 @@ where
None => return Ok(()), // zero-sized access
};
let tcx = &*self.tcx;
let tcx = *self.tcx;
// FIXME: We should check that there are dest.layout.size many bytes available in
// memory. The code below is not sufficient, with enough padding it might not
// cover all the bytes!
@ -776,12 +787,14 @@ where
Immediate::Scalar(scalar) => {
match dest.layout.abi {
Abi::Scalar(_) => {} // fine
_ => {
bug!("write_immediate_to_mplace: invalid Scalar layout: {:#?}", dest.layout)
}
_ => span_bug!(
self.cur_span(),
"write_immediate_to_mplace: invalid Scalar layout: {:#?}",
dest.layout
),
}
self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(
tcx,
&tcx,
ptr,
scalar,
dest.layout.size,
@ -793,7 +806,8 @@ where
// which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
let (a, b) = match dest.layout.abi {
Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
_ => bug!(
_ => span_bug!(
self.cur_span(),
"write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
dest.layout
),
@ -806,8 +820,8 @@ where
// but that does not work: We could be a newtype around a pair, then the
// fields do not match the `ScalarPair` components.
self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(tcx, ptr, a_val, a_size)?;
self.memory.get_raw_mut(b_ptr.alloc_id)?.write_scalar(tcx, b_ptr, b_val, b_size)
self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(&tcx, ptr, a_val, a_size)?;
self.memory.get_raw_mut(b_ptr.alloc_id)?.write_scalar(&tcx, b_ptr, b_val, b_size)
}
}
}
@ -841,9 +855,9 @@ where
) -> InterpResult<'tcx> {
// We do NOT compare the types for equality, because well-typed code can
// actually "transmute" `&mut T` to `&T` in an assignment without a cast.
if !mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
if !mir_assign_valid_types(*self.tcx, src.layout, dest.layout) {
span_bug!(
self.tcx.span,
self.cur_span(),
"type mismatch when copying!\nsrc: {:?},\ndest: {:?}",
src.layout.ty,
dest.layout.ty,
@ -898,7 +912,7 @@ where
src: OpTy<'tcx, M::PointerTag>,
dest: PlaceTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx> {
if mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
if mir_assign_valid_types(*self.tcx, src.layout, dest.layout) {
// Fast path: Just use normal `copy_op`
return self.copy_op(src, dest);
}
@ -910,7 +924,7 @@ where
// on `typeck_tables().has_errors` at all const eval entry points.
debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
self.tcx.sess.delay_span_bug(
self.tcx.span,
self.cur_span(),
"size-changing transmute, should have been caught by transmute checking",
);
throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));

View file

@ -76,7 +76,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
info!("{:?}", stmt);
self.set_span(stmt.source_info.span);
use rustc_middle::mir::StatementKind::*;
@ -279,7 +278,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
info!("{:?}", terminator.kind);
self.set_span(terminator.source_info.span);
self.eval_terminator(terminator)?;
if !self.stack().is_empty() {

View file

@ -2,7 +2,7 @@ use std::convert::TryFrom;
use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
use rustc_target::abi::{Align, LayoutOf, Size};
use super::{FnVal, InterpCx, Machine, MemoryKind};
@ -49,8 +49,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let size = layout.size.bytes();
let align = layout.align.abi.bytes();
let tcx = *self.tcx;
let ptr_size = self.pointer_size();
let ptr_align = self.tcx.data_layout.pointer_align.abi;
let ptr_align = tcx.data_layout.pointer_align.abi;
// /////////////////////////////////////////////////////////////////////////////////////////
// If you touch this code, be sure to also make the corresponding changes to
// `get_vtable` in `rust_codegen_llvm/meth.rs`.
@ -60,33 +61,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ptr_align,
MemoryKind::Vtable,
);
let tcx = &*self.tcx;
let drop = Instance::resolve_drop_in_place(*tcx, ty);
let drop = Instance::resolve_drop_in_place(tcx, ty);
let drop = self.memory.create_fn_alloc(FnVal::Instance(drop));
// No need to do any alignment checks on the memory accesses below, because we know the
// allocation is correctly aligned as we created it above. Also we're only offsetting by
// multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
let vtable_alloc = self.memory.get_raw_mut(vtable.alloc_id)?;
vtable_alloc.write_ptr_sized(tcx, vtable, drop.into())?;
vtable_alloc.write_ptr_sized(&tcx, vtable, drop.into())?;
let size_ptr = vtable.offset(ptr_size, tcx)?;
vtable_alloc.write_ptr_sized(tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
let align_ptr = vtable.offset(ptr_size * 2, tcx)?;
vtable_alloc.write_ptr_sized(tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?;
let size_ptr = vtable.offset(ptr_size, &tcx)?;
vtable_alloc.write_ptr_sized(&tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
let align_ptr = vtable.offset(ptr_size * 2, &tcx)?;
vtable_alloc.write_ptr_sized(&tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?;
for (i, method) in methods.iter().enumerate() {
if let Some((def_id, substs)) = *method {
// resolve for vtable: insert shims where needed
let instance =
ty::Instance::resolve_for_vtable(*tcx, self.param_env, def_id, substs)
ty::Instance::resolve_for_vtable(tcx, self.param_env, def_id, substs)
.ok_or_else(|| err_inval!(TooGeneric))?;
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
// We cannot use `vtable_allic` as we are creating fn ptrs in this loop.
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), tcx)?;
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &tcx)?;
self.memory.get_raw_mut(vtable.alloc_id)?.write_ptr_sized(
tcx,
&tcx,
method_ptr,
fn_ptr.into(),
)?;
@ -171,7 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
alloc.read_ptr_sized(self, vtable.offset(pointer_size * 2, self)?)?.not_undef()?;
let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
if size >= self.tcx.data_layout().obj_size_bound() {
if size >= self.tcx.data_layout.obj_size_bound() {
throw_ub_format!(
"invalid vtable: \
size is bigger than largest supported object"

View file

@ -313,7 +313,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
let param_env = tcx.param_env(def_id).with_reveal_all();
let span = tcx.def_span(def_id);
let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine::new(), ());
let mut ecx = InterpCx::new(tcx, span, param_env, ConstPropMachine::new(), ());
let can_const_prop = CanConstProp::check(body);
let ret = ecx
@ -404,9 +404,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
match self.ecx.eval_const_to_op(c.literal, None) {
Ok(op) => Some(op),
Err(error) => {
// Make sure errors point at the constant.
self.ecx.set_span(c.span);
let err = error_to_const_error(&self.ecx, error);
let tcx = self.ecx.tcx.at(c.span);
let err = error_to_const_error(&self.ecx, error, Some(c.span));
if let Some(lint_root) = self.lint_root(source_info) {
let lint_only = match c.literal.val {
// Promoteds must lint and not error as the user didn't ask for them
@ -418,17 +417,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
if lint_only {
// Out of backwards compatibility we cannot report hard errors in unused
// generic functions using associated constants of the generic parameters.
err.report_as_lint(
self.ecx.tcx,
"erroneous constant used",
lint_root,
Some(c.span),
);
err.report_as_lint(tcx, "erroneous constant used", lint_root, Some(c.span));
} else {
err.report_as_error(self.ecx.tcx, "erroneous constant used");
err.report_as_error(tcx, "erroneous constant used");
}
} else {
err.report_as_error(self.ecx.tcx, "erroneous constant used");
err.report_as_error(tcx, "erroneous constant used");
}
None
}
@ -852,7 +846,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
trace!("visit_statement: {:?}", statement);
let source_info = statement.source_info;
self.ecx.set_span(source_info.span);
self.source_info = Some(source_info);
if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind {
let place_ty: Ty<'tcx> = place.ty(&self.local_decls, self.tcx).ty;
@ -865,7 +858,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
if let Some(value) = self.get_const(place) {
if self.should_const_prop(value) {
trace!("replacing {:?} with {:?}", rval, value);
self.replace_with_const(rval, value, statement.source_info);
self.replace_with_const(rval, value, source_info);
if can_const_prop == ConstPropMode::FullConstProp
|| can_const_prop == ConstPropMode::OnlyInsideOwnBlock
{
@ -928,7 +921,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
let source_info = terminator.source_info;
self.ecx.set_span(source_info.span);
self.source_info = Some(source_info);
self.super_terminator(terminator, location);
match &mut terminator.kind {

View file

@ -91,7 +91,7 @@ impl<K: DepKind> fmt::Debug for DepNode<K> {
}
pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
const CAN_RECONSTRUCT_QUERY_KEY: bool;
fn can_reconstruct_query_key() -> bool;
/// This method turns the parameters of a DepNodeConstructor into an opaque
/// Fingerprint to be used in DepNode.
@ -108,7 +108,7 @@ pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
/// This method tries to recover the query key from the given `DepNode`,
/// something which is needed when forcing `DepNode`s during red-green
/// evaluation. The query system will only call this method if
/// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
/// `can_reconstruct_query_key()` is `true`.
/// It is always valid to return `None` here, in which case incremental
/// compilation will treat the query as having changed instead of forcing it.
fn recover(tcx: Ctxt, dep_node: &DepNode<Ctxt::DepKind>) -> Option<Self>;
@ -118,7 +118,10 @@ impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T
where
T: HashStable<Ctxt::StableHashingContext> + fmt::Debug,
{
default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
#[inline]
default fn can_reconstruct_query_key() -> bool {
false
}
default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint {
let mut hcx = tcx.create_stable_hashing_context();

View file

@ -4,7 +4,7 @@
#![feature(const_panic)]
#![feature(core_intrinsics)]
#![feature(hash_raw_entry)]
#![feature(specialization)] // FIXME: min_specialization rejects `default const`
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]
#![feature(vec_remove_item)]

View file

@ -10,7 +10,7 @@ Core encoding and decoding interfaces.
test(attr(allow(unused_variables), deny(warnings)))
)]
#![feature(box_syntax)]
#![feature(specialization)] // FIXME: min_specialization does not work
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(nll)]
#![feature(associated_type_bounds)]

View file

@ -635,24 +635,6 @@ impl<T> Decodable for PhantomData<T> {
}
}
impl<'a, T: ?Sized + Encodable> Encodable for &'a T {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
impl<T: ?Sized + Encodable> Encodable for Box<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
impl<T: Decodable> Decodable for Box<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
Ok(box Decodable::decode(d)?)
}
}
impl<T: Decodable> Decodable for Box<[T]> {
fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
let v: Vec<T> = Decodable::decode(d)?;
@ -1008,8 +990,20 @@ impl<T: UseSpecializedDecodable> Decodable for T {
// for this exact reason.
// May be fixable in a simpler fashion via the
// more complex lattice model for specialization.
impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {}
impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {}
impl<T: Decodable> UseSpecializedDecodable for Box<T> {}
impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
impl<T: Decodable> UseSpecializedDecodable for Box<T> {
fn default_decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
Ok(box Decodable::decode(d)?)
}
}
impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {}
impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {}

View file

@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+neon,+fp-armv8,+cyclone".to_string(),
features: "+neon,+fp-armv8,+apple-a7".to_string(),
eliminate_frame_pointer: false,
max_atomic_width: Some(128),
abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
features: "+neon,+fp-armv8,+cyclone".to_string(),
features: "+neon,+fp-armv8,+apple-a7".to_string(),
eliminate_frame_pointer: false,
max_atomic_width: Some(128),
abi_blacklist: super::arm_base::abi_blacklist(),

View file

@ -122,7 +122,7 @@ fn target_cpu(arch: Arch) -> String {
match arch {
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
Armv7s => "cortex-a9",
Arm64 => "cyclone",
Arm64 => "apple-a7",
I386 => "yonah",
X86_64 => "core2",
X86_64_macabi => "core2",

View file

@ -90,7 +90,7 @@ pub trait InferCtxtBuilderExt<'tcx> {
where
K: TypeFoldable<'tcx>,
R: Debug + TypeFoldable<'tcx>,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable;
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
}
impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
@ -118,7 +118,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
where
K: TypeFoldable<'tcx>,
R: Debug + TypeFoldable<'tcx>,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
{
self.enter_with_canonical(
DUMMY_SP,

View file

@ -16,7 +16,6 @@
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
#![feature(or_patterns)]
#![feature(option_zip)]
#![recursion_limit = "512"] // For rustdoc
#[macro_use]

View file

@ -1747,24 +1747,41 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
pub fn recursive_type_with_infinite_size_error(
tcx: TyCtxt<'tcx>,
type_def_id: DefId,
) -> DiagnosticBuilder<'tcx> {
spans: Vec<Span>,
) {
assert!(type_def_id.is_local());
let span = tcx.hir().span_if_local(type_def_id).unwrap();
let span = tcx.sess.source_map().guess_head_span(span);
let mut err = struct_span_err!(
tcx.sess,
span,
E0072,
"recursive type `{}` has infinite size",
tcx.def_path_str(type_def_id)
);
let path = tcx.def_path_str(type_def_id);
let mut err =
struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
err.span_label(span, "recursive type has infinite size");
err.help(&format!(
"insert indirection (e.g., a `Box`, `Rc`, or `&`) \
at some point to make `{}` representable",
tcx.def_path_str(type_def_id)
));
err
for &span in &spans {
err.span_label(span, "recursive without indirection");
}
let msg = format!(
"insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
path,
);
if spans.len() <= 4 {
err.multipart_suggestion(
&msg,
spans
.iter()
.flat_map(|&span| {
vec![
(span.shrink_to_lo(), "Box<".to_string()),
(span.shrink_to_hi(), ">".to_string()),
]
.into_iter()
})
.collect(),
Applicability::HasPlaceholders,
);
} else {
err.help(&msg);
}
err.emit();
}
/// Summarizes information

View file

@ -2387,11 +2387,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bo
// caught by case 1.
match rty.is_representable(tcx, sp) {
Representability::SelfRecursive(spans) => {
let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id());
for span in spans {
err.span_label(span, "recursive without indirection");
}
err.emit();
recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
return false;
}
Representability::Representable | Representability::ContainsRecursive => (),

View file

@ -41,7 +41,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
[target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies]
hermit-abi = { version = "0.1.13", features = ['rustc-dep-of-std'] }
hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] }
[target.wasm32-wasi.dependencies]
wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }

View file

@ -234,15 +234,14 @@ pub struct NulError(usize, Vec<u8>);
/// An error indicating that a nul byte was not in the expected position.
///
/// The slice used to create a [`CStr`] must have one and only one nul
/// byte at the end of the slice.
/// The slice used to create a [`CStr`] must have one and only one nul byte,
/// positioned at the end.
///
/// This error is created by the
/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
/// [`CStr`]. See its documentation for more.
/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`].
/// See its documentation for more.
///
/// [`CStr`]: struct.CStr.html
/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
///
/// # Examples
///
@ -257,6 +256,32 @@ pub struct FromBytesWithNulError {
kind: FromBytesWithNulErrorKind,
}
/// An error indicating that a nul byte was not in the expected position.
///
/// The vector used to create a [`CString`] must have one and only one nul byte,
/// positioned at the end.
///
/// This error is created by the [`from_vec_with_nul`] method on [`CString`].
/// See its documentation for more.
///
/// [`CString`]: struct.CString.html
/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
///
/// # Examples
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// use std::ffi::{CString, FromVecWithNulError};
///
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
/// ```
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
pub struct FromVecWithNulError {
error_kind: FromBytesWithNulErrorKind,
bytes: Vec<u8>,
}
#[derive(Clone, PartialEq, Eq, Debug)]
enum FromBytesWithNulErrorKind {
InteriorNul(usize),
@ -272,6 +297,59 @@ impl FromBytesWithNulError {
}
}
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
impl FromVecWithNulError {
/// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`].
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// use std::ffi::CString;
///
/// // Some invalid bytes in a vector
/// let bytes = b"f\0oo".to_vec();
///
/// let value = CString::from_vec_with_nul(bytes.clone());
///
/// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
/// ```
///
/// [`CString`]: struct.CString.html
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..]
}
/// Returns the bytes that were attempted to convert to a [`CString`].
///
/// This method is carefully constructed to avoid allocation. It will
/// consume the error, moving out the bytes, so that a copy of the bytes
/// does not need to be made.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// use std::ffi::CString;
///
/// // Some invalid bytes in a vector
/// let bytes = b"f\0oo".to_vec();
///
/// let value = CString::from_vec_with_nul(bytes.clone());
///
/// assert_eq!(bytes, value.unwrap_err().into_bytes());
/// ```
///
/// [`CString`]: struct.CString.html
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
}
/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
///
/// `CString` is just a wrapper over a buffer of bytes with a nul
@ -643,6 +721,86 @@ impl CString {
let this = mem::ManuallyDrop::new(self);
unsafe { ptr::read(&this.inner) }
}
/// Converts a `Vec` of `u8` to a `CString` without checking the invariants
/// on the given `Vec`.
///
/// # Safety
///
/// The given `Vec` **must** have one nul byte as its last element.
/// This means it cannot be empty nor have any other nul byte anywhere else.
///
/// # Example
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// use std::ffi::CString;
/// assert_eq!(
/// unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
/// unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
/// );
/// ```
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
Self { inner: v.into_boxed_slice() }
}
/// Attempts to converts a `Vec` of `u8` to a `CString`.
///
/// Runtime checks are present to ensure there is only one nul byte in the
/// `Vec`, its last element.
///
/// # Errors
///
/// If a nul byte is present and not the last element or no nul bytes
/// is present, an error will be returned.
///
/// # Examples
///
/// A successful conversion will produce the same result as [`new`] when
/// called without the ending nul byte.
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// use std::ffi::CString;
/// assert_eq!(
/// CString::from_vec_with_nul(b"abc\0".to_vec())
/// .expect("CString::from_vec_with_nul failed"),
/// CString::new(b"abc".to_vec()).expect("CString::new failed")
/// );
/// ```
///
/// A incorrectly formatted vector will produce an error.
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// use std::ffi::{CString, FromVecWithNulError};
/// // Interior nul byte
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
/// // No nul byte
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
/// ```
///
/// [`new`]: #method.new
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
let nul_pos = memchr::memchr(0, &v);
match nul_pos {
Some(nul_pos) if nul_pos + 1 == v.len() => {
// SAFETY: We know there is only one nul byte, at the end
// of the vec.
Ok(unsafe { Self::from_vec_with_nul_unchecked(v) })
}
Some(nul_pos) => Err(FromVecWithNulError {
error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
bytes: v,
}),
None => Err(FromVecWithNulError {
error_kind: FromBytesWithNulErrorKind::NotNulTerminated,
bytes: v,
}),
}
}
}
// Turns this `CString` into an empty string to prevent
@ -976,6 +1134,23 @@ impl fmt::Display for FromBytesWithNulError {
}
}
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
impl Error for FromVecWithNulError {}
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
impl fmt::Display for FromVecWithNulError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.error_kind {
FromBytesWithNulErrorKind::InteriorNul(pos) => {
write!(f, "data provided contains an interior nul byte at pos {}", pos)
}
FromBytesWithNulErrorKind::NotNulTerminated => {
write!(f, "data provided is not nul terminated")
}
}
}
}
impl IntoStringError {
/// Consumes this error, returning original [`CString`] which generated the
/// error.

View file

@ -157,6 +157,8 @@
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::FromBytesWithNulError;
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
pub use self::c_str::FromVecWithNulError;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CStr, CString, IntoStringError, NulError};

View file

@ -694,42 +694,6 @@ impl PartialEq for SocketAddrV6 {
&& self.inner.sin6_scope_id == other.inner.sin6_scope_id
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl PartialEq<SocketAddrV4> for SocketAddr {
fn eq(&self, other: &SocketAddrV4) -> bool {
match self {
SocketAddr::V4(v4) => v4 == other,
SocketAddr::V6(_) => false,
}
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl PartialEq<SocketAddrV6> for SocketAddr {
fn eq(&self, other: &SocketAddrV6) -> bool {
match self {
SocketAddr::V4(_) => false,
SocketAddr::V6(v6) => v6 == other,
}
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl PartialEq<SocketAddr> for SocketAddrV4 {
fn eq(&self, other: &SocketAddr) -> bool {
match other {
SocketAddr::V4(v4) => self == v4,
SocketAddr::V6(_) => false,
}
}
}
#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
impl PartialEq<SocketAddr> for SocketAddrV6 {
fn eq(&self, other: &SocketAddr) -> bool {
match other {
SocketAddr::V4(_) => false,
SocketAddr::V6(v6) => self == v6,
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Eq for SocketAddrV4 {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1242,12 +1206,8 @@ mod tests {
// equality
assert_eq!(v4_1, v4_1);
assert_eq!(v6_1, v6_1);
assert_eq!(v4_1, SocketAddr::V4(v4_1));
assert_eq!(v6_1, SocketAddr::V6(v6_1));
assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
assert!(v4_1 != SocketAddr::V6(v6_1));
assert!(v6_1 != SocketAddr::V4(v4_1));
assert!(v4_1 != v4_2);
assert!(v6_1 != v6_2);
@ -1268,5 +1228,10 @@ mod tests {
assert!(v6_1 < v6_3);
assert!(v4_3 > v4_1);
assert!(v6_3 > v6_1);
// compare with an inferred right-hand side
assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
}
}

View file

@ -107,6 +107,60 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
///
/// *guard += 1;
/// ```
///
/// It is sometimes necessary to manually drop the mutex guard to unlock it
/// sooner than the end of the enclosing scope.
///
/// ```
/// use std::sync::{Arc, Mutex};
/// use std::thread;
///
/// const N: usize = 3;
///
/// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4]));
/// let res_mutex = Arc::new(Mutex::new(0));
///
/// let mut threads = Vec::with_capacity(N);
/// (0..N).for_each(|_| {
/// let data_mutex_clone = Arc::clone(&data_mutex);
/// let res_mutex_clone = Arc::clone(&res_mutex);
///
/// threads.push(thread::spawn(move || {
/// let mut data = data_mutex_clone.lock().unwrap();
/// // This is the result of some important and long-ish work.
/// let result = data.iter().fold(0, |acc, x| acc + x * 2);
/// data.push(result);
/// drop(data);
/// *res_mutex_clone.lock().unwrap() += result;
/// }));
/// });
///
/// let mut data = data_mutex.lock().unwrap();
/// // This is the result of some important and long-ish work.
/// let result = data.iter().fold(0, |acc, x| acc + x * 2);
/// data.push(result);
/// // We drop the `data` explicitly because it's not necessary anymore and the
/// // thread still has work to do. This allow other threads to start working on
/// // the data immediately, without waiting for the rest of the unrelated work
/// // to be done here.
/// //
/// // It's even more important here than in the threads because we `.join` the
/// // threads after that. If we had not dropped the mutex guard, a thread could
/// // be waiting forever for it, causing a deadlock.
/// drop(data);
/// // Here the mutex guard is not assigned to a variable and so, even if the
/// // scope does not end after this line, the mutex is still released: there is
/// // no deadlock.
/// *res_mutex.lock().unwrap() += result;
///
/// threads.into_iter().for_each(|thread| {
/// thread
/// .join()
/// .expect("The thread creating or execution failed !")
/// });
///
/// assert_eq!(*res_mutex.lock().unwrap(), 800);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
pub struct Mutex<T: ?Sized> {

View file

@ -1,10 +1,13 @@
use crate::convert::TryFrom;
use crate::fmt;
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::str;
use crate::sync::Arc;
use crate::sys::hermit::abi;
use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6};
use crate::sys::{unsupported, Void};
use crate::sys_common::AsInner;
use crate::time::Duration;
/// Checks whether the HermitCore's socket interface has been started already, and
@ -17,14 +20,33 @@ pub fn init() -> io::Result<()> {
Ok(())
}
pub struct TcpStream(abi::Handle);
#[derive(Debug, Clone)]
pub struct Socket(abi::Handle);
impl AsInner<abi::Handle> for Socket {
fn as_inner(&self) -> &abi::Handle {
&self.0
}
}
impl Drop for Socket {
fn drop(&mut self) {
let _ = abi::tcpstream::close(self.0);
}
}
// Arc is used to count the number of used sockets.
// Only if all sockets are released, the drop
// method will close the socket.
#[derive(Clone)]
pub struct TcpStream(Arc<Socket>);
impl TcpStream {
pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
let addr = addr?;
match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
Ok(handle) => Ok(TcpStream(handle)),
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => {
Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
}
@ -37,7 +59,7 @@ impl TcpStream {
saddr.port(),
Some(duration.as_millis() as u64),
) {
Ok(handle) => Ok(TcpStream(handle)),
Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
_ => {
Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
}
@ -45,31 +67,34 @@ impl TcpStream {
}
pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
abi::tcpstream::set_read_timeout(self.0, duration.map(|d| d.as_millis() as u64))
abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
}
pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
abi::tcpstream::set_write_timeout(self.0, duration.map(|d| d.as_millis() as u64))
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
abi::tcpstream::set_write_timeout(
*self.0.as_inner(),
duration.map(|d| d.as_millis() as u64),
)
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
let duration = abi::tcpstream::get_read_timeout(self.0)
let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
Ok(duration.map(|d| Duration::from_millis(d)))
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
let duration = abi::tcpstream::get_write_timeout(self.0)
let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
Ok(duration.map(|d| Duration::from_millis(d)))
}
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
abi::tcpstream::peek(self.0, buf)
abi::tcpstream::peek(*self.0.as_inner(), buf)
.map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
}
@ -81,18 +106,11 @@ impl TcpStream {
let mut size: usize = 0;
for i in ioslice.iter_mut() {
let mut pos: usize = 0;
let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
while pos < i.len() {
let ret = abi::tcpstream::read(self.0, &mut i[pos..])
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
if ret == 0 {
return Ok(size);
} else {
size += ret;
pos += ret;
}
if ret != 0 {
size += ret;
}
}
@ -112,7 +130,7 @@ impl TcpStream {
let mut size: usize = 0;
for i in ioslice.iter() {
size += abi::tcpstream::write(self.0, i)
size += abi::tcpstream::write(*self.0.as_inner(), i)
.map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?;
}
@ -125,7 +143,21 @@ impl TcpStream {
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported"))
let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?;
let saddr = match ipaddr {
Ipv4(ref addr) => SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
port,
),
Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
_ => {
return Err(io::Error::new(ErrorKind::Other, "peer_addr failed"));
}
};
Ok(saddr)
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
@ -133,34 +165,31 @@ impl TcpStream {
}
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
abi::tcpstream::shutdown(self.0, how as i32)
abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket"))
}
pub fn duplicate(&self) -> io::Result<TcpStream> {
let handle = abi::tcpstream::duplicate(self.0)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?;
Ok(TcpStream(handle))
Ok(self.clone())
}
pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nodelay(self.0, mode)
abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
}
pub fn nodelay(&self) -> io::Result<bool> {
abi::tcpstream::nodelay(self.0)
abi::tcpstream::nodelay(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed"))
}
pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
abi::tcpstream::set_tll(self.0, tll)
abi::tcpstream::set_tll(*self.0.as_inner(), tll)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL"))
}
pub fn ttl(&self) -> io::Result<u32> {
abi::tcpstream::get_tll(self.0)
abi::tcpstream::get_tll(*self.0.as_inner())
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL"))
}
@ -169,40 +198,50 @@ impl TcpStream {
}
pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nonblocking(self.0, mode)
abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode"))
}
}
impl Drop for TcpStream {
fn drop(&mut self) {
let _ = abi::tcpstream::close(self.0);
}
}
impl fmt::Debug for TcpStream {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
pub struct TcpListener(abi::Handle);
#[derive(Clone)]
pub struct TcpListener(SocketAddr);
impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
let addr = addr?;
Ok(TcpListener(*addr))
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
Ok(self.0)
}
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
.map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?;
let saddr = match ipaddr {
Ipv4(ref addr) => SocketAddr::new(
IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
port,
),
Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
_ => {
return Err(io::Error::new(ErrorKind::Other, "accept failed"));
}
};
Ok((TcpStream(Arc::new(Socket(handle))), saddr))
}
pub fn duplicate(&self) -> io::Result<TcpListener> {
Err(io::Error::new(ErrorKind::Other, "not supported"))
Ok(self.clone())
}
pub fn set_ttl(&self, _: u32) -> io::Result<()> {

View file

@ -23,10 +23,10 @@ LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable
error[E0080]: evaluation of constant value failed
--> $DIR/infinite_loop.rs:8:20
--> $DIR/infinite_loop.rs:8:17
|
LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
| ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
error: aborting due to 3 previous errors

View file

@ -17,8 +17,8 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
note: ...which requires const-evaluating `std::mem::size_of`...
--> $SRC_DIR/libcore/mem/mod.rs:LL:COL
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | pub const fn size_of<T>() -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|

View file

@ -1,15 +1,18 @@
error: any use of this value will cause an error
--> $DIR/const_eval_limit_reached.rs:8:11
--> $DIR/const_eval_limit_reached.rs:8:5
|
LL | / const X: usize = {
LL | | let mut x = 0;
LL | | while x != 1000 {
| | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
LL | |
... |
LL | | x
LL | | };
| |__-
LL | / const X: usize = {
LL | | let mut x = 0;
LL | | while x != 1000 {
| |_____^
LL | ||
LL | || x += 1;
LL | || }
| ||_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
LL | |
LL | | x
LL | | };
| |__-
|
= note: `#[deny(const_err)]` on by default

View file

@ -1,8 +1,8 @@
error[E0391]: cycle detected when const-evaluating `FOO`
--> $DIR/recursive-zst-static.rs:10:18
--> $DIR/recursive-zst-static.rs:10:1
|
LL | static FOO: () = FOO;
| ^^^
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `FOO`...
--> $DIR/recursive-zst-static.rs:10:1

View file

@ -1,8 +1,8 @@
error[E0391]: cycle detected when const-evaluating `FOO`
--> $DIR/recursive-zst-static.rs:10:18
--> $DIR/recursive-zst-static.rs:10:1
|
LL | static FOO: () = FOO;
| ^^^
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `FOO`...
--> $DIR/recursive-zst-static.rs:10:1

View file

@ -1,11 +1,11 @@
// build-fail
pub const unsafe fn fake_type<T>() -> T {
hint_unreachable()
hint_unreachable() //~ ERROR evaluation of constant value failed
}
pub const unsafe fn hint_unreachable() -> ! {
fake_type() //~ ERROR evaluation of constant value failed
fake_type()
}
trait Const {

View file

@ -1,9 +1,10 @@
error[E0080]: evaluation of constant value failed
--> $DIR/uninhabited-const-issue-61744.rs:8:5
--> $DIR/uninhabited-const-issue-61744.rs:4:5
|
LL | hint_unreachable()
| ------------------
| ^^^^^^^^^^^^^^^^^^
| |
| reached the configured maximum number of stack frames
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
@ -71,9 +72,8 @@ LL | hint_unreachable()
| inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
...
LL | fake_type()
| ^^^^^^^^^^^
| -----------
| |
| reached the configured maximum number of stack frames
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
| inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5

View file

@ -1,14 +1,14 @@
error[E0391]: cycle detected when const-evaluating `a`
--> $DIR/infinite-recursion-const-fn.rs:3:25
--> $DIR/infinite-recursion-const-fn.rs:3:1
|
LL | const fn a() -> usize { b() }
| ^^^
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `b`...
--> $DIR/infinite-recursion-const-fn.rs:4:25
--> $DIR/infinite-recursion-const-fn.rs:4:1
|
LL | const fn b() -> usize { a() }
| ^^^
| ^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires const-evaluating `a`, completing the cycle
note: cycle used when const-evaluating `ARR::{{constant}}#0`
--> $DIR/infinite-recursion-const-fn.rs:5:18

View file

@ -6,7 +6,10 @@ LL | enum MList { Cons(isize, MList), Nil }
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable
|
LL | enum MList { Cons(isize, Box<MList>), Nil }
| ^^^^ ^
error[E0391]: cycle detected when computing drop-check constraints for `MList`
--> $DIR/infinite-tag-type-recursion.rs:1:1

View file

@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-1.rs:1:1
|
LL | struct Foo { foo: Option<Option<Foo>> }
| ^^^^^^^^^^ ------------------------ recursive without indirection
| ^^^^^^^^^^ ------------------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { foo: Box<Option<Option<Foo>>> }
| ^^^^ ^
error: aborting due to previous error

View file

@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
--> $DIR/issue-17431-2.rs:1:1
|
LL | struct Baz { q: Option<Foo> }
| ^^^^^^^^^^ -------------- recursive without indirection
| ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
|
LL | struct Baz { q: Box<Option<Foo>> }
| ^^^^ ^
error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-2.rs:4:1
|
LL | struct Foo { q: Option<Baz> }
| ^^^^^^^^^^ -------------- recursive without indirection
| ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { q: Box<Option<Baz>> }
| ^^^^ ^
error: aborting due to 2 previous errors

View file

@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-3.rs:3:1
|
LL | struct Foo { foo: Mutex<Option<Foo>> }
| ^^^^^^^^^^ ----------------------- recursive without indirection
| ^^^^^^^^^^ ------------------ recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
| ^^^^ ^
error: aborting due to previous error

View file

@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-4.rs:3:1
|
LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
| ^^^^^^^^^^^^^ --------------------------- recursive without indirection
| ^^^^^^^^^^^^^ ---------------------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
| ^^^^ ^
error: aborting due to previous error

View file

@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
--> $DIR/issue-17431-5.rs:5:1
|
LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
| ^^^^^^^^^^^^^ ----------- recursive without indirection
| ^^^^^^^^^^^^^ -------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
|
LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
| ^^^^ ^
error: aborting due to previous error

View file

@ -6,7 +6,10 @@ LL | enum Foo { X(Mutex<Option<Foo>>) }
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
| ^^^^ ^
error: aborting due to previous error

View file

@ -6,7 +6,10 @@ LL | enum Foo { Voo(Option<Option<Foo>>) }
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
| ^^^^ ^
error: aborting due to previous error

View file

@ -7,7 +7,10 @@ LL | pub struct Pong(SendPacket<Ping>);
| | recursive without indirection
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable
|
LL | pub struct Pong(Box<SendPacket<Ping>>);
| ^^^^ ^
error: aborting due to previous error

View file

@ -7,7 +7,10 @@ LL | enum Bar {
LL | BarSome(Bar)
| --- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
|
LL | BarSome(Box<Bar>)
| ^^^^ ^
error: aborting due to previous error

View file

@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
--> $DIR/issue-3008-2.rs:2:1
|
LL | struct Bar { x: Bar }
| ^^^^^^^^^^ ------ recursive without indirection
| ^^^^^^^^^^ --- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
|
LL | struct Bar { x: Box<Bar> }
| ^^^^ ^
error: aborting due to previous error

View file

@ -6,7 +6,10 @@ LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable
|
LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
| ^^^^ ^
error: aborting due to previous error

View file

@ -8,7 +8,10 @@ LL | Plus(Expr, Expr),
| |
| recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable
|
LL | Plus(Box<Expr>, Box<Expr>),
| ^^^^ ^ ^^^^ ^
error: aborting due to previous error

View file

@ -5,9 +5,12 @@ LL | struct S {
| ^^^^^^^^ recursive type has infinite size
LL |
LL | element: Option<S>
| ------------------ recursive without indirection
| --------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
|
LL | element: Box<Option<S>>
| ^^^^ ^
error: aborting due to previous error

View file

@ -7,7 +7,10 @@ LL | Class(ClassTypeSignature),
LL | Array(TypeSignature),
| ------------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable
|
LL | Array(Box<TypeSignature>),
| ^^^^ ^
error[E0072]: recursive type `TypeSignature` has infinite size
--> $DIR/issue-57271.rs:19:1
@ -18,7 +21,10 @@ LL | Base(BaseType),
LL | Object(ObjectType),
| ---------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable
|
LL | Object(Box<ObjectType>),
| ^^^^ ^
error: aborting due to 2 previous errors

View file

@ -6,7 +6,10 @@ LL | pub enum ElemDerived {
LL | A(ElemDerived)
| ----------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ElemDerived` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived` representable
|
LL | A(Box<ElemDerived>)
| ^^^^ ^
error: aborting due to previous error

View file

@ -6,7 +6,10 @@ LL | enum List<T> { Cons(T, List<T>), Nil }
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
|
LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
| ^^^^ ^
error: aborting due to previous error

View file

@ -1,8 +1,8 @@
error[E0391]: cycle detected when const-evaluating `FOO`
--> $DIR/recursive-static-definition.rs:1:23
--> $DIR/recursive-static-definition.rs:1:1
|
LL | pub static FOO: u32 = FOO;
| ^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `FOO`...
--> $DIR/recursive-static-definition.rs:1:1

View file

@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
--> $DIR/sized-cycle-note.rs:9:1
|
LL | struct Baz { q: Option<Foo> }
| ^^^^^^^^^^ -------------- recursive without indirection
| ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
|
LL | struct Baz { q: Box<Option<Foo>> }
| ^^^^ ^
error[E0072]: recursive type `Foo` has infinite size
--> $DIR/sized-cycle-note.rs:11:1
|
LL | struct Foo { q: Option<Baz> }
| ^^^^^^^^^^ -------------- recursive without indirection
| ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { q: Box<Option<Baz>> }
| ^^^^ ^
error: aborting due to 2 previous errors

View file

@ -5,9 +5,12 @@ LL | struct ListNode {
| ^^^^^^^^^^^^^^^ recursive type has infinite size
LL | head: u8,
LL | tail: Option<ListNode>,
| ---------------------- recursive without indirection
| ---------------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
|
LL | tail: Box<Option<ListNode>>,
| ^^^^ ^
error: aborting due to previous error

View file

@ -6,11 +6,14 @@ LL | | ListNode
LL | | {
LL | | head: u8,
LL | | tail: Option<ListNode>,
| | ---------------------- recursive without indirection
| | ---------------- recursive without indirection
LL | | }
| |_^ recursive type has infinite size
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
|
LL | tail: Box<Option<ListNode>>,
| ^^^^ ^
error: aborting due to previous error

View file

@ -4,9 +4,12 @@ error[E0072]: recursive type `Foo` has infinite size
LL | struct Foo<'a> {
| ^^^^^^^^^^^^^^ recursive type has infinite size
LL | bar: Bar<'a>,
| ------------ recursive without indirection
| ------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | bar: Box<Bar<'a>>,
| ^^^^ ^
error[E0072]: recursive type `Bar` has infinite size
--> $DIR/recursive-type-field.rs:8:1
@ -14,18 +17,18 @@ error[E0072]: recursive type `Bar` has infinite size
LL | struct Bar<'a> {
| ^^^^^^^^^^^^^^ recursive type has infinite size
LL | y: (Foo<'a>, Foo<'a>),
| --------------------- recursive without indirection
| ------------------ recursive without indirection
LL | z: Option<Bar<'a>>,
| ------------------ recursive without indirection
| --------------- recursive without indirection
...
LL | d: [Bar<'a>; 1],
| --------------- recursive without indirection
| ------------ recursive without indirection
LL | e: Foo<'a>,
| ---------- recursive without indirection
| ------- recursive without indirection
LL | x: Bar<'a>,
| ---------- recursive without indirection
| ------- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
= help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
error: aborting due to 2 previous errors

View file

@ -5,9 +5,12 @@ LL | struct T1 {
| ^^^^^^^^^ recursive type has infinite size
LL | foo: isize,
LL | foolish: T1
| ----------- recursive without indirection
| -- recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T1` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable
|
LL | foolish: Box<T1>
| ^^^^ ^
error: aborting due to previous error

View file

@ -5,9 +5,12 @@ LL | union U {
| ^^^^^^^ recursive type has infinite size
LL | a: u8,
LL | b: U,
| ---- recursive without indirection
| - recursive without indirection
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `U` representable
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable
|
LL | b: Box<U>,
| ^^^^ ^
error: aborting due to previous error

View file

@ -5,10 +5,10 @@ LL | pub static mut B: () = unsafe { A = 1; };
| ^^^^^ modifying a static's initial value from another static's initializer
error[E0391]: cycle detected when const-evaluating `C`
--> $DIR/write-to-static-mut-in-static.rs:5:34
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `C`...
--> $DIR/write-to-static-mut-in-static.rs:5:1

View file

@ -88,7 +88,7 @@ fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr<'_>, right: &'a Exp
let upper = check_upper_bound(l);
let lower = check_lower_bound(r);
transpose(upper, lower).and_then(|(l, r)| l.combine(r, cx))
upper.zip(lower).and_then(|(l, r)| l.combine(r, cx))
};
upper_lower(left, right).or_else(|| upper_lower(right, left))
@ -131,7 +131,10 @@ impl<'a> Conversion<'a> {
/// Checks if the to-type is the same (if there is a type constraint)
fn has_compatible_to_type(&self, other: &Self) -> bool {
transpose(self.to_type.as_ref(), other.to_type.as_ref()).map_or(true, |(l, r)| l == r)
match (self.to_type, other.to_type) {
(Some(l), Some(r)) => l == r,
_ => true,
}
}
/// Try to construct a new conversion if the conversion type is valid
@ -322,14 +325,6 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
}
}
/// (Option<T>, Option<U>) -> Option<(T, U)>
fn transpose<T, U>(lhs: Option<T>, rhs: Option<U>) -> Option<(T, U)> {
match (lhs, rhs) {
(Some(l), Some(r)) => Some((l, r)),
_ => None,
}
}
/// Will return the expressions as if they were expr1 <= expr2
fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
match op.node {