summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-16 08:48:36 +0000
committerbors <bors@rust-lang.org>2022-07-16 08:48:36 +0000
commite092d0b6b43f2de967af0887873151bb1c0b18d3 (patch)
tree3c0903d6cb6800cbf43017141fc38b669a360386
parenta8314ef7d0ec7b75c336af2c9857bfaf43002bfc (diff)
parent647922f9d8a6f1fa639ab206e60a76d43cc9d3dd (diff)
downloadrust-1.62.1.tar.gz
Auto merge of #99299 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum1.62.1
[stable] 1.62.1 release This bundles: * Windows: Fallback for overlapped I/O #98950 * don't succeed evaluate_obligation query if new opaque types were registered #98614 * Mitigate MMIO stale data vulnerability #98126 * Return a FxIndexSet in is_late_bound query. #99219 Also bumps the version number to 1.62.1 and includes a short release notes section for the release. r? `@Mark-Simulacrum`
-rw-r--r--RELEASES.md18
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs2
-rw-r--r--compiler/rustc_infer/src/infer/undo_log.rs4
-rw-r--r--compiler/rustc_infer/src/traits/project.rs2
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/middle/resolve_lifetime.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/traits/select.rs18
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/query.rs2
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_type_ir/src/lib.rs8
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/alloc.rs120
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/mod.rs2
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/tests.rs30
-rw-r--r--library/std/src/sys/windows/c.rs14
-rw-r--r--library/std/src/sys/windows/handle.rs25
-rw-r--r--library/std/src/sys/windows/handle/tests.rs22
-rw-r--r--src/test/incremental/async-lifetimes.rs19
-rw-r--r--src/test/ui-fulldeps/issue-81357-unsound-file-methods.rs81
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.rs1
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr112
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/inference-cycle.stderr27
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98604.rs13
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98604.stderr18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98608.rs9
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-98608.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/reveal_local.rs1
-rw-r--r--src/test/ui/type-alias-impl-trait/reveal_local.stderr33
-rw-r--r--src/version2
36 files changed, 442 insertions, 212 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 3d88891ad21..fa82077e65b 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,21 @@
+Version 1.62.1 (2022-07-19)
+==========================
+
+Rust 1.62.1 addresses a few recent regressions in the compiler and standard
+library, and also mitigates a CPU vulnerability on Intel SGX.
+
+* [The compiler fixed unsound function coercions involving `impl Trait` return types.][98608]
+* [The compiler fixed an incremental compilation bug with `async fn` lifetimes.][98890]
+* [Windows added a fallback for overlapped I/O in synchronous reads and writes.][98950]
+* [The `x86_64-fortanix-unknown-sgx` target added a mitigation for the
+ MMIO stale data vulnerability][98126], advisory [INTEL-SA-00615].
+
+[98608]: https://github.com/rust-lang/rust/issues/98608
+[98890]: https://github.com/rust-lang/rust/issues/98890
+[98950]: https://github.com/rust-lang/rust/pull/98950
+[98126]: https://github.com/rust-lang/rust/pull/98126
+[INTEL-SA-00615]: https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html
+
Version 1.62.0 (2022-06-30)
==========================
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c9121f7d348..989cc551a82 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -929,6 +929,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
}
+ pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'a, 'tcx>) -> bool {
+ self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
+ }
+
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
}
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 92c0ed84057..3b9b6f7a2af 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -99,7 +99,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
- ty::Opaque(def_id, substs) => {
+ ty::Opaque(def_id, substs) if def_id.is_local() => {
let origin = if self.defining_use_anchor.is_some() {
// Check that this is `impl Trait` type is
// declared by `parent_def_id` -- i.e., one whose
diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs
index 1b696f21cbc..74a26ebc39f 100644
--- a/compiler/rustc_infer/src/infer/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/undo_log.rs
@@ -185,6 +185,10 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
})
}
+ pub(crate) fn opaque_types_in_snapshot(&self, s: &Snapshot<'tcx>) -> bool {
+ self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..)))
+ }
+
pub(crate) fn region_constraints(
&self,
) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index b84ed3dc689..18469208731 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -203,7 +203,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => {
info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
let mut ty = ty.clone();
- if result == EvaluationResult::EvaluatedToOk {
+ if result.must_apply_considering_regions() {
ty.obligations = vec![];
}
map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) });
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 7c90cbb9092..c1ec5d68a7b 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -85,6 +85,7 @@ macro_rules! arena_types {
[] attribute: rustc_ast::Attribute,
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
[] hir_id_set: rustc_hir::HirIdSet,
+ [] late_bound_lifetimes: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
// Interned types
[] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>,
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index 70586cefaee..11ce6313147 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -2,7 +2,7 @@
use crate::ty;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::ItemLocalId;
use rustc_macros::HashStable;
@@ -64,7 +64,7 @@ pub struct ResolveLifetimes {
/// Set of lifetime def ids that are late-bound; a region can
/// be late-bound if (a) it does NOT appear in a where-clause and
/// (b) it DOES appear in the arguments.
- pub late_bound: FxHashMap<LocalDefId, FxHashSet<LocalDefId>>,
+ pub late_bound: FxHashMap<LocalDefId, FxIndexSet<LocalDefId>>,
pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6d7ec247d04..a23ff302a40 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1537,7 +1537,7 @@ rustc_queries! {
Option<&'tcx FxHashMap<ItemLocalId, Region>> {
desc { "looking up a named region" }
}
- query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
+ query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxIndexSet<LocalDefId>)> {
desc { "testing if a region is late bound" }
}
/// For a given item (like a struct), gets the default lifetimes to be used
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index ffa70cddbd5..854dd215a37 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -176,6 +176,10 @@ pub enum EvaluationResult {
EvaluatedToOk,
/// Evaluation successful, but there were unevaluated region obligations.
EvaluatedToOkModuloRegions,
+ /// Evaluation successful, but need to rerun because opaque types got
+ /// hidden types assigned without it being known whether the opaque types
+ /// are within their defining scope
+ EvaluatedToOkModuloOpaqueTypes,
/// Evaluation is known to be ambiguous -- it *might* hold for some
/// assignment of inference variables, but it might not.
///
@@ -252,9 +256,11 @@ impl EvaluationResult {
pub fn may_apply(self) -> bool {
match self {
- EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
- true
- }
+ EvaluatedToOkModuloOpaqueTypes
+ | EvaluatedToOk
+ | EvaluatedToOkModuloRegions
+ | EvaluatedToAmbig
+ | EvaluatedToUnknown => true,
EvaluatedToErr | EvaluatedToRecur => false,
}
@@ -264,7 +270,11 @@ impl EvaluationResult {
match self {
EvaluatedToUnknown | EvaluatedToRecur => true,
- EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
+ EvaluatedToOkModuloOpaqueTypes
+ | EvaluatedToOk
+ | EvaluatedToOkModuloRegions
+ | EvaluatedToAmbig
+ | EvaluatedToErr => false,
}
}
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 1c552591b11..a254979162e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1065,6 +1065,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
Lift
)]
pub struct OpaqueTypeKey<'tcx> {
+ // FIXME(oli-obk): make this a LocalDefId
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index fb937ded65a..1bb49a59ba4 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -36,7 +36,7 @@ use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, T
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::Lrc;
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index ff75e4eae35..9b4184840bd 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -8,7 +8,7 @@
use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
use rustc_ast::walk_list;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@@ -482,6 +482,11 @@ fn convert_named_region_map(tcx: TyCtxt<'_>, named_region_map: NamedRegionMap) -
let def_id = tcx.hir().local_def_id(hir_id);
map.insert(def_id);
}
+ for (_, late_bound) in &mut rl.late_bound {
+ late_bound.sort_by(|&a, &b| {
+ tcx.def_path_hash(a.to_def_id()).cmp(&tcx.def_path_hash(b.to_def_id()))
+ });
+ }
for (hir_id, v) in named_region_map.late_bound_vars {
let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
map.insert(hir_id.local_id, v);
@@ -540,7 +545,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
fn is_late_bound_map<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
-) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
+) -> Option<(LocalDefId, &'tcx FxIndexSet<LocalDefId>)> {
match tcx.def_kind(def_id) {
DefKind::AnonConst | DefKind::InlineConst => {
let mut def_id = tcx.local_parent(def_id);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index d20ba99ebc9..60cb5914dad 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -761,6 +761,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
Ok(
EvaluationResult::EvaluatedToOk
| EvaluationResult::EvaluatedToOkModuloRegions
+ | EvaluationResult::EvaluatedToOkModuloOpaqueTypes
| EvaluationResult::EvaluatedToAmbig,
) => {}
_ => return false,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 1c9f83f8f34..ed4877638bf 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -388,6 +388,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Err(_) => return Ok(EvaluatedToErr),
}
+ if self.infcx.opaque_types_added_in_snapshot(snapshot) {
+ return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));
+ }
+
match self.infcx.region_constraints_added_in_snapshot(snapshot) {
None => Ok(result),
Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index c63e9c31d53..a46729f229e 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -61,14 +61,6 @@ bitflags! {
| TypeFlags::HAS_CT_INFER.bits
| TypeFlags::HAS_TY_PLACEHOLDER.bits
| TypeFlags::HAS_CT_PLACEHOLDER.bits
- // The `evaluate_obligation` query does not return further
- // obligations. If it evaluates an obligation with an opaque
- // type, that opaque type may get compared to another type,
- // constraining it. We would lose this information.
- // FIXME: differentiate between crate-local opaque types
- // and opaque types from other crates, as only opaque types
- // from the local crate can possibly be a local name
- | TypeFlags::HAS_TY_OPAQUE.bits
// We consider 'freshened' types and constants
// to depend on a particular fn.
// The freshening process throws away information,
diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
index 3792a3820a5..ea24fedd0eb 100644
--- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
@@ -1,13 +1,16 @@
#![allow(unused)]
+use crate::arch::asm;
use crate::cell::UnsafeCell;
+use crate::cmp;
+use crate::convert::TryInto;
use crate::mem;
use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
use crate::ptr::{self, NonNull};
use crate::slice;
use crate::slice::SliceIndex;
-use super::super::mem::is_user_range;
+use super::super::mem::{is_enclave_range, is_user_range};
use fortanix_sgx_abi::*;
/// A type that can be safely read from or written to userspace.
@@ -210,7 +213,9 @@ where
unsafe {
// Mustn't call alloc with size 0.
let ptr = if size > 0 {
- rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
+ // `copy_to_userspace` is more efficient when data is 8-byte aligned
+ let alignment = cmp::max(T::align_of(), 8);
+ rtunwrap!(Ok, super::alloc(size, alignment)) as _
} else {
T::align_of() as _ // dangling pointer ok for size 0
};
@@ -225,13 +230,9 @@ where
/// Copies `val` into freshly allocated space in user memory.
pub fn new_from_enclave(val: &T) -> Self {
unsafe {
- let ret = Self::new_uninit_bytes(mem::size_of_val(val));
- ptr::copy(
- val as *const T as *const u8,
- ret.0.as_ptr() as *mut u8,
- mem::size_of_val(val),
- );
- ret
+ let mut user = Self::new_uninit_bytes(mem::size_of_val(val));
+ user.copy_from_enclave(val);
+ user
}
}
@@ -304,6 +305,105 @@ where
}
}
+/// Copies `len` bytes of data from enclave pointer `src` to userspace `dst`
+///
+/// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either:
+/// - preceded by the VERW instruction and followed by the MFENCE; LFENCE instruction sequence
+/// - or are in multiples of 8 bytes, aligned to an 8-byte boundary
+///
+/// # Panics
+/// This function panics if:
+///
+/// * The `src` pointer is null
+/// * The `dst` pointer is null
+/// * The `src` memory range is not in enclave memory
+/// * The `dst` memory range is not in user memory
+///
+/// # References
+/// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html
+/// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/processor-mmio-stale-data-vulnerabilities.html#inpage-nav-3-2-2
+pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
+ unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
+ unsafe {
+ let mut seg_sel: u16 = 0;
+ for off in 0..len {
+ asm!("
+ mov %ds, ({seg_sel})
+ verw ({seg_sel})
+ movb {val}, ({dst})
+ mfence
+ lfence
+ ",
+ val = in(reg_byte) *src.offset(off as isize),
+ dst = in(reg) dst.offset(off as isize),
+ seg_sel = in(reg) &mut seg_sel,
+ options(nostack, att_syntax)
+ );
+ }
+ }
+ }
+
+ unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
+ unsafe {
+ asm!(
+ "rep movsq (%rsi), (%rdi)",
+ inout("rcx") len / 8 => _,
+ inout("rdi") dst => _,
+ inout("rsi") src => _,
+ options(att_syntax, nostack, preserves_flags)
+ );
+ }
+ }
+ assert!(!src.is_null());
+ assert!(!dst.is_null());
+ assert!(is_enclave_range(src, len));
+ assert!(is_user_range(dst, len));
+ assert!(len < isize::MAX as usize);
+ assert!(!(src as usize).overflowing_add(len).1);
+ assert!(!(dst as usize).overflowing_add(len).1);
+
+ if len < 8 {
+ // Can't align on 8 byte boundary: copy safely byte per byte
+ unsafe {
+ copy_bytewise_to_userspace(src, dst, len);
+ }
+ } else if len % 8 == 0 && dst as usize % 8 == 0 {
+ // Copying 8-byte aligned quadwords: copy quad word per quad word
+ unsafe {
+ copy_aligned_quadwords_to_userspace(src, dst, len);
+ }
+ } else {
+ // Split copies into three parts:
+ // +--------+
+ // | small0 | Chunk smaller than 8 bytes
+ // +--------+
+ // | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
+ // +--------+
+ // | small1 | Chunk smaller than 8 bytes
+ // +--------+
+
+ unsafe {
+ // Copy small0
+ let small0_size = (8 - dst as usize % 8) as u8;
+ let small0_src = src;
+ let small0_dst = dst;
+ copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _);
+
+ // Copy big
+ let small1_size = ((len - small0_size as usize) % 8) as u8;
+ let big_size = len - small0_size as usize - small1_size as usize;
+ let big_src = src.offset(small0_size as _);
+ let big_dst = dst.offset(small0_size as _);
+ copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size);
+
+ // Copy small1
+ let small1_src = src.offset(big_size as isize + small0_size as isize);
+ let small1_dst = dst.offset(big_size as isize + small0_size as isize);
+ copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _);
+ }
+ }
+}
+
#[unstable(feature = "sgx_platform", issue = "56975")]
impl<T: ?Sized> UserRef<T>
where
@@ -352,7 +452,7 @@ where
pub fn copy_from_enclave(&mut self, val: &T) {
unsafe {
assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get()));
- ptr::copy(
+ copy_to_userspace(
val as *const T as *const u8,
self.0.get() as *mut T as *mut u8,
mem::size_of_val(val),
diff --git a/library/std/src/sys/sgx/abi/usercalls/mod.rs b/library/std/src/sys/sgx/abi/usercalls/mod.rs
index 2f99abba776..79d1db5e1c5 100644
--- a/library/std/src/sys/sgx/abi/usercalls/mod.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/mod.rs
@@ -6,6 +6,8 @@ use crate::time::{Duration, Instant};
pub(crate) mod alloc;
#[macro_use]
pub(crate) mod raw;
+#[cfg(test)]
+mod tests;
use self::raw::*;
diff --git a/library/std/src/sys/sgx/abi/usercalls/tests.rs b/library/std/src/sys/sgx/abi/usercalls/tests.rs
new file mode 100644
index 00000000000..cbf7d7d54f7
--- /dev/null
+++ b/library/std/src/sys/sgx/abi/usercalls/tests.rs
@@ -0,0 +1,30 @@
+use super::alloc::copy_to_userspace;
+use super::alloc::User;
+
+#[test]
+fn test_copy_function() {
+ let mut src = [0u8; 100];
+ let mut dst = User::<[u8]>::uninitialized(100);
+
+ for i in 0..src.len() {
+ src[i] = i as _;
+ }
+
+ for size in 0..48 {
+ // For all possible alignment
+ for offset in 0..8 {
+ // overwrite complete dst
+ dst.copy_from_enclave(&[0u8; 100]);
+
+ // Copy src[0..size] to dst + offset
+ unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().offset(offset), size) };
+
+ // Verify copy
+ for byte in 0..size {
+ unsafe {
+ assert_eq!(*dst.as_ptr().offset(offset + byte as isize), src[byte as usize]);
+ }
+ }
+ }
+ }
+}
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 5f14edaf067..b92aa420177 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -325,7 +325,9 @@ union IO_STATUS_BLOCK_union {
}
impl Default for IO_STATUS_BLOCK_union {
fn default() -> Self {
- Self { Pointer: ptr::null_mut() }
+ let mut this = Self { Pointer: ptr::null_mut() };
+ this.Status = STATUS_PENDING;
+ this
}
}
#[repr(C)]
@@ -334,6 +336,16 @@ pub struct IO_STATUS_BLOCK {
u: IO_STATUS_BLOCK_union,
pub Information: usize,
}
+impl IO_STATUS_BLOCK {
+ pub fn status(&self) -> NTSTATUS {
+ // SAFETY: If `self.u.Status` was set then this is obviously safe.
+ // If `self.u.Pointer` was set then this is the equivalent to converting
+ // the pointer to an integer, which is also safe.
+ // Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
+ // this module is to call the `default` method, which sets the `Status`.
+ unsafe { self.u.Status }
+ }
+}
pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn(
dwErrorCode: DWORD,
diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs
index ef9a8bd6900..6398c445633 100644
--- a/library/std/src/sys/windows/handle.rs
+++ b/library/std/src/sys/windows/handle.rs
@@ -1,5 +1,8 @@
#![unstable(issue = "none", feature = "windows_handle")]
+#[cfg(test)]
+mod tests;
+
use crate::cmp;
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf};
use crate::mem;
@@ -248,14 +251,18 @@ impl Handle {
offset.map(|n| n as _).as_ref(),
None,
);
+
+ let status = if status == c::STATUS_PENDING {
+ c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
+ io_status.status()
+ } else {
+ status
+ };
match status {
// If the operation has not completed then abort the process.
// Doing otherwise means that the buffer and stack may be written to
// after this function returns.
- c::STATUS_PENDING => {
- eprintln!("I/O error: operation failed to complete synchronously");
- crate::process::abort();
- }
+ c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
// Return `Ok(0)` when there's nothing more to read.
c::STATUS_END_OF_FILE => Ok(0),
@@ -294,13 +301,17 @@ impl Handle {
None,
)
};
+ let status = if status == c::STATUS_PENDING {
+ unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
+ io_status.status()
+ } else {
+ status
+ };
match status {
// If the operation has not completed then abort the process.
// Doing otherwise means that the buffer may be read and the stack
// written to after this function returns.
- c::STATUS_PENDING => {
- rtabort!("I/O error: operation failed to complete synchronously");
- }
+ c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"),
// Success!
status if c::nt_success(status) => Ok(io_status.Information),
diff --git a/library/std/src/sys/windows/handle/tests.rs b/library/std/src/sys/windows/handle/tests.rs
new file mode 100644
index 00000000000..d836dae4c30
--- /dev/null
+++ b/library/std/src/sys/windows/handle/tests.rs
@@ -0,0 +1,22 @@
+use crate::sys::pipe::{anon_pipe, Pipes};
+use crate::{thread, time};
+
+/// Test the synchronous fallback for overlapped I/O.
+#[test]
+fn overlapped_handle_fallback() {
+ // Create some pipes. `ours` will be asynchronous.
+ let Pipes { ours, theirs } = anon_pipe(true, false).unwrap();
+
+ let async_readable = ours.into_handle();
+ let sync_writeable = theirs.into_handle();
+
+ thread::scope(|_| {
+ thread::sleep(time::Duration::from_millis(100));
+ sync_writeable.write(b"hello world!").unwrap();
+ });
+
+ // The pipe buffer starts empty so reading won't complete synchronously unless
+ // our fallback path works.
+ let mut buffer = [0u8; 1024];
+ async_readable.read(&mut buffer).unwrap();
+}
diff --git a/src/test/incremental/async-lifetimes.rs b/src/test/incremental/async-lifetimes.rs
new file mode 100644
index 00000000000..90a0b93b99a
--- /dev/null
+++ b/src/test/incremental/async-lifetimes.rs
@@ -0,0 +1,19 @@
+// revisions: rpass1 rpass2
+// edition:2021
+
+// See https://github.com/rust-lang/rust/issues/98890
+
+#![allow(unused)]
+
+struct Foo;
+
+impl Foo {
+ async fn f(&self, _: &&()) -> &() {
+ &()
+ }
+}
+
+#[cfg(rpass2)]
+enum Bar {}
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/issue-81357-unsound-file-methods.rs b/src/test/ui-fulldeps/issue-81357-unsound-file-methods.rs
new file mode 100644
index 00000000000..fdf1150f8d2
--- /dev/null
+++ b/src/test/ui-fulldeps/issue-81357-unsound-file-methods.rs
@@ -0,0 +1,81 @@
+// run-fail
+// only-windows
+
+fn main() {
+ use std::fs;
+ use std::io::prelude::*;
+ use std::os::windows::prelude::*;
+ use std::ptr;
+ use std::sync::Arc;
+ use std::thread;
+ use std::time::Duration;
+
+ const FILE_FLAG_OVERLAPPED: u32 = 0x40000000;
+
+ fn create_pipe_server(path: &str) -> fs::File {
+ let mut path0 = path.as_bytes().to_owned();
+ path0.push(0);
+ extern "system" {
+ fn CreateNamedPipeA(
+ lpName: *const u8,
+ dwOpenMode: u32,
+ dwPipeMode: u32,
+ nMaxInstances: u32,
+ nOutBufferSize: u32,
+ nInBufferSize: u32,
+ nDefaultTimeOut: u32,
+ lpSecurityAttributes: *mut u8,
+ ) -> RawHandle;
+ }
+
+ unsafe {
+ let h = CreateNamedPipeA(path0.as_ptr(), 3, 0, 1, 0, 0, 0, ptr::null_mut());
+ assert_ne!(h as isize, -1);
+ fs::File::from_raw_handle(h)
+ }
+ }
+
+ let path = "\\\\.\\pipe\\repro";
+ let mut server = create_pipe_server(path);
+
+ let client = Arc::new(
+ fs::OpenOptions::new().custom_flags(FILE_FLAG_OVERLAPPED).read(true).open(path).unwrap(),
+ );
+
+ let spawn_read = |is_first: bool| {
+ thread::spawn({
+ let f = client.clone();
+ move || {
+ let mut buf = [0xcc; 1];
+ let mut f = f.as_ref();
+ f.read(&mut buf).unwrap();
+ if is_first {
+ assert_ne!(buf[0], 0xcc);
+ } else {
+ let b = buf[0]; // capture buf[0]
+ thread::sleep(Duration::from_millis(200));
+
+ // Check the buffer hasn't been written to after read.
+ dbg!(buf[0], b);
+ assert_eq!(buf[0], b);
+ }
+ }
+ })
+ };
+
+ let t1 = spawn_read(true);
+ thread::sleep(Duration::from_millis(20));
+ let t2 = spawn_read(false);
+ thread::sleep(Duration::from_millis(100));
+ let _ = server.write(b"x");
+ thread::sleep(Duration::from_millis(100));
+ let _ = server.write(b"y");
+
+ // This is run fail because we need to test for the `abort`.
+ // That failing to run is the success case.
+ if t1.join().is_err() || t2.join().is_err() {
+ return;
+ } else {
+ panic!("success");
+ }
+}
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index d2452abab02..c2fbbf94fd6 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -11,7 +11,6 @@ fn main() {
// return type, which can't depend on the obligation.
fn cycle1() -> impl Clone {
//~^ ERROR cycle detected
- //~| ERROR cycle detected
send(cycle2().clone());
Rc::new(Cell::new(5))
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 14db864f1c2..634ff14869e 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -30,129 +30,47 @@ note: ...which requires building MIR for `cycle1`...
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires computing type of `cycle2::{opaque#0}`...
- --> $DIR/auto-trait-leak.rs:20:16
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in top-level module
- --> $DIR/auto-trait-leak.rs:1:1
- |
-LL | / use std::cell::Cell;
-LL | | use std::rc::Rc;
-LL | |
-LL | | fn send<T: Send>(_: T) {}
-... |
-LL | | Rc::new(String::from("foo"))
-LL | | }
- | |_^
-
-error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
- --> $DIR/auto-trait-leak.rs:12:16
+ --> $DIR/auto-trait-leak.rs:14:5
|
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^
- |
-note: ...which requires borrow-checking `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle1`...
- --> $DIR/auto-trait-leak.rs:12:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | send(cycle2().clone());
+ | ^^^^
+ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
note: ...which requires computing type of `cycle2::{opaque#0}`...
- --> $DIR/auto-trait-leak.rs:20:16
+ --> $DIR/auto-trait-leak.rs:19:16
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^
note: ...which requires borrow-checking `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
+ --> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
+ --> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing MIR for `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
+ --> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires unsafety-checking `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
+ --> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
+ --> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `cycle2`...
- --> $DIR/auto-trait-leak.rs:20:1
+ --> $DIR/auto-trait-leak.rs:20:5
|
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | send(cycle1().clone());
+ | ^^^^
+ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
= note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/auto-trait-leak.rs:1:1
@@ -166,6 +84,6 @@ LL | | Rc::new(String::from("foo"))
LL | | }
| |_^
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
index b456b1445e7..5fb7a9473d3 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
@@ -6,7 +6,6 @@
mod m {
type Foo = impl std::fmt::Debug;
//~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
- //~| ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
pub fn foo() -> Foo {
22_u32
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
index 4c44875b4a5..1e9a45aac79 100644
--- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
@@ -5,10 +5,11 @@ LL | type Foo = impl std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires type-checking `m::bar`...
- --> $DIR/auto-trait-leakage3.rs:15:5
+ --> $DIR/auto-trait-leakage3.rs:15:9
|
-LL | pub fn bar() {
- | ^^^^^^^^^^^^
+LL | is_send(foo());
+ | ^^^^^^^
+ = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
note: cycle used when checking item types in module `m`
--> $DIR/auto-trait-leakage3.rs:6:1
@@ -16,24 +17,6 @@ note: cycle used when checking item types in module `m`
LL | mod m {
| ^^^^^
-error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
- --> $DIR/auto-trait-leakage3.rs:7:16
- |
-LL | type Foo = impl std::fmt::Debug;
- | ^^^^^^^^^^^^^^^^^^^^
- |
-note: ...which requires type-checking `m::bar`...
- --> $DIR/auto-trait-leakage3.rs:15:5
- |
-LL | pub fn bar() {
- | ^^^^^^^^^^^^
- = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in module `m`
- --> $DIR/auto-trait-leakage3.rs:6:1
- |
-LL | mod m {
- | ^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
index 608572978a3..79caddf7913 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.rs
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
@@ -4,7 +4,6 @@
mod m {
type Foo = impl std::fmt::Debug;
//~^ ERROR cycle detected
- //~| ERROR cycle detected
// Cycle: error today, but it'd be nice if it eventually worked
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
index 3ed86fae8a1..b9d646b927a 100644
--- a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
+++ b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
@@ -5,10 +5,11 @@ LL | type Foo = impl std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires type-checking `m::bar`...
- --> $DIR/inference-cycle.rs:15:5
+ --> $DIR/inference-cycle.rs:15:9
|
-LL | pub fn bar() {
- | ^^^^^^^^^^^^
+LL | is_send(foo()); // Today: error
+ | ^^^^^^^
+ = note: ...which requires evaluating trait selection obligation `m::Foo: core::marker::Send`...
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
note: cycle used when checking item types in module `m`
--> $DIR/inference-cycle.rs:4:1
@@ -16,24 +17,6 @@ note: cycle used when checking item types in module `m`
LL | mod m {
| ^^^^^
-error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
- --> $DIR/inference-cycle.rs:5:16
- |
-LL | type Foo = impl std::fmt::Debug;
- | ^^^^^^^^^^^^^^^^^^^^
- |
-note: ...which requires type-checking `m::bar`...
- --> $DIR/inference-cycle.rs:15:5
- |
-LL | pub fn bar() {
- | ^^^^^^^^^^^^
- = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in module `m`
- --> $DIR/inference-cycle.rs:4:1
- |
-LL | mod m {
- | ^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-98604.rs b/src/test/ui/type-alias-impl-trait/issue-98604.rs
new file mode 100644
index 00000000000..a4fd8a82a04
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98604.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+type AsyncFnPtr = Box<
+ dyn Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = ()>>>,
+>;
+
+async fn test() {}
+
+#[allow(unused_must_use)]
+fn main() {
+ Box::new(test) as AsyncFnPtr;
+ //~^ ERROR type mismatch
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-98604.stderr b/src/test/ui/type-alias-impl-trait/issue-98604.stderr
new file mode 100644
index 00000000000..ad3982760c3
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98604.stderr
@@ -0,0 +1,18 @@
+error[E0271]: type mismatch resolving `<fn() -> impl Future<Output = ()> {test} as FnOnce<()>>::Output == Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+ --> $DIR/issue-98604.rs:11:5
+ |
+LL | Box::new(test) as AsyncFnPtr;
+ | ^^^^^^^^^^^^^^ expected struct `Pin`, found opaque type
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-98604.rs:7:17
+ |
+LL | async fn test() {}
+ | ^ checked the `Output` of this `async fn`, found opaque type
+ = note: expected struct `Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+ found opaque type `impl Future<Output = ()>`
+ = note: required for the cast to the object type `dyn Fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-98608.rs b/src/test/ui/type-alias-impl-trait/issue-98608.rs
new file mode 100644
index 00000000000..d75762a8b62
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98608.rs
@@ -0,0 +1,9 @@
+fn hi() -> impl Sized { std::ptr::null::<u8>() }
+
+fn main() {
+ let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
+ //~^ ERROR type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>`
+ let boxed = b();
+ let null = *boxed;
+ println!("{null:?}");
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-98608.stderr b/src/test/ui/type-alias-impl-trait/issue-98608.stderr
new file mode 100644
index 00000000000..6773b01112d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-98608.stderr
@@ -0,0 +1,16 @@
+error[E0271]: type mismatch resolving `<fn() -> impl Sized {hi} as FnOnce<()>>::Output == Box<u8>`
+ --> $DIR/issue-98608.rs:4:39
+ |
+LL | fn hi() -> impl Sized { std::ptr::null::<u8>() }
+ | ---------- the found opaque type
+...
+LL | let b: Box<dyn Fn() -> Box<u8>> = Box::new(hi);
+ | ^^^^^^^^^^^^ expected struct `Box`, found opaque type
+ |
+ = note: expected struct `Box<u8>`
+ found opaque type `impl Sized`
+ = note: required for the cast to the object type `dyn Fn() -> Box<u8>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.rs b/src/test/ui/type-alias-impl-trait/reveal_local.rs
index 145186baa1f..7ecb5535301 100644
--- a/src/test/ui/type-alias-impl-trait/reveal_local.rs
+++ b/src/test/ui/type-alias-impl-trait/reveal_local.rs
@@ -4,7 +4,6 @@ use std::fmt::Debug;
type Foo = impl Debug;
//~^ ERROR cycle detected
-//~| ERROR cycle detected
fn is_send<T: Send>() { }
diff --git a/src/test/ui/type-alias-impl-trait/reveal_local.stderr b/src/test/ui/type-alias-impl-trait/reveal_local.stderr
index 5d48dd5b2bf..27fded33329 100644
--- a/src/test/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/src/test/ui/type-alias-impl-trait/reveal_local.stderr
@@ -5,10 +5,11 @@ LL | type Foo = impl Debug;
| ^^^^^^^^^^
|
note: ...which requires type-checking `not_good`...
- --> $DIR/reveal_local.rs:11:1
+ --> $DIR/reveal_local.rs:13:5
|
-LL | fn not_good() {
- | ^^^^^^^^^^^^^
+LL | is_send::<Foo>();
+ | ^^^^^^^^^^^^^^
+ = note: ...which requires evaluating trait selection obligation `Foo: core::marker::Send`...
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/reveal_local.rs:1:1
@@ -22,30 +23,6 @@ LL | |
LL | | fn main() {}
| |____________^
-error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
- --> $DIR/reveal_local.rs:5:12
- |
-LL | type Foo = impl Debug;
- | ^^^^^^^^^^
- |
-note: ...which requires type-checking `not_gooder`...
- --> $DIR/reveal_local.rs:17:1
- |
-LL | fn not_gooder() {
- | ^^^^^^^^^^^^^^^
- = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking item types in top-level module
- --> $DIR/reveal_local.rs:1:1
- |
-LL | / #![feature(type_alias_impl_trait)]
-LL | |
-LL | | use std::fmt::Debug;
-LL | |
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0391`.
diff --git a/src/version b/src/version
index 76d05362056..b77a81dcb12 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.62.0
+1.62.1