mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #112716 - compiler-errors:rollup-h77daia, r=compiler-errors
Rollup of 7 pull requests Successful merges: - #111074 (Relax implicit `T: Sized` bounds on `BufReader<T>`, `BufWriter<T>` and `LineWriter<T>`) - #112226 (std: available_parallelism using native netbsd api first) - #112474 (Support 128-bit enum variant in debuginfo codegen) - #112662 (`#[lang_item]` for `core::ptr::Unique`) - #112665 (Make assumption functions in new solver take `Binder<'tcx, Clause<'tcx>>`) - #112684 (Disable alignment checks on i686-pc-windows-msvc) - #112706 (Add `SyntaxContext::is_root`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
670a0edaa9
@ -108,6 +108,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
self.const_uint(self.type_u64(), i)
|
||||
}
|
||||
|
||||
fn const_u128(&self, i: u128) -> RValue<'gcc> {
|
||||
self.const_uint_big(self.type_u128(), i)
|
||||
}
|
||||
|
||||
fn const_usize(&self, i: u64) -> RValue<'gcc> {
|
||||
let bit_size = self.data_layout().pointer_size.bits();
|
||||
if bit_size < 64 {
|
||||
@ -254,7 +258,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
// SIMD builtins require a constant value.
|
||||
self.bitcast_if_needed(value, typ)
|
||||
}
|
||||
|
||||
|
||||
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
|
||||
self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None)
|
||||
}
|
||||
|
@ -168,6 +168,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
self.const_uint(self.type_i64(), i)
|
||||
}
|
||||
|
||||
fn const_u128(&self, i: u128) -> &'ll Value {
|
||||
self.const_uint_big(self.type_i128(), i)
|
||||
}
|
||||
|
||||
fn const_usize(&self, i: u64) -> &'ll Value {
|
||||
let bit_size = self.data_layout().pointer_size.bits();
|
||||
if bit_size < 64 {
|
||||
|
@ -429,7 +429,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
|
||||
return existing_di_node;
|
||||
}
|
||||
|
||||
debug!("type_di_node: {:?}", t);
|
||||
debug!("type_di_node: {:?} kind: {:?}", t, t.kind());
|
||||
|
||||
let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() {
|
||||
ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
|
||||
|
@ -412,13 +412,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
|
||||
enum_type_and_layout.size.bits(),
|
||||
enum_type_and_layout.align.abi.bits() as u32,
|
||||
Size::ZERO.bits(),
|
||||
discr_value.opt_single_val().map(|value| {
|
||||
// NOTE(eddyb) do *NOT* remove this assert, until
|
||||
// we pass the full 128-bit value to LLVM, otherwise
|
||||
// truncation will be silent and remain undetected.
|
||||
assert_eq!(value as u64 as u128, value);
|
||||
cx.const_u64(value as u64)
|
||||
}),
|
||||
discr_value.opt_single_val().map(|value| cx.const_u128(value)),
|
||||
DIFlags::FlagZero,
|
||||
variant_member_info.variant_struct_type_di_node,
|
||||
)
|
||||
|
@ -15,6 +15,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
|
||||
fn const_i32(&self, i: i32) -> Self::Value;
|
||||
fn const_u32(&self, i: u32) -> Self::Value;
|
||||
fn const_u64(&self, i: u64) -> Self::Value;
|
||||
fn const_u128(&self, i: u128) -> Self::Value;
|
||||
fn const_usize(&self, i: u64) -> Self::Value;
|
||||
fn const_u8(&self, i: u8) -> Self::Value;
|
||||
fn const_real(&self, t: Self::Type, val: f64) -> Self::Value;
|
||||
|
@ -9,7 +9,7 @@ use rustc_session::parse::{feature_err, ParseSess};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{Span, SyntaxContext};
|
||||
use rustc_span::Span;
|
||||
|
||||
const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
|
||||
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
|
||||
@ -72,7 +72,7 @@ pub(super) fn parse(
|
||||
// `SyntaxContext::root()` from a foreign crate will
|
||||
// have the edition of that crate (which we manually
|
||||
// retrieve via the `edition` parameter).
|
||||
if span.ctxt() == SyntaxContext::root() {
|
||||
if span.ctxt().is_root() {
|
||||
edition
|
||||
} else {
|
||||
span.edition()
|
||||
|
@ -260,6 +260,8 @@ language_item_table! {
|
||||
EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None;
|
||||
|
||||
OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1);
|
||||
// Experimental language item for Miri
|
||||
PtrUnique, sym::ptr_unique, ptr_unique, Target::Struct, GenericRequirement::Exact(1);
|
||||
|
||||
PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
|
||||
|
||||
|
@ -3,7 +3,7 @@ use rustc_middle::hir;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::MirSpanview;
|
||||
use rustc_span::{BytePos, Pos, Span, SyntaxContext};
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
|
||||
use std::cmp;
|
||||
use std::io::{self, Write};
|
||||
@ -327,7 +327,7 @@ fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
|
||||
let mut span = data.terminator().source_info.span;
|
||||
for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
|
||||
// Only combine Spans from the root context, and within the function's body_span.
|
||||
if statement_span.ctxt() == SyntaxContext::root() && body_span.contains(statement_span) {
|
||||
if statement_span.ctxt().is_root() && body_span.contains(statement_span) {
|
||||
span = span.to(statement_span);
|
||||
}
|
||||
}
|
||||
|
@ -586,6 +586,24 @@ pub enum Clause<'tcx> {
|
||||
ConstArgHasType(Const<'tcx>, Ty<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> Binder<'tcx, Clause<'tcx>> {
|
||||
pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
|
||||
if let ty::Clause::Trait(trait_clause) = self.skip_binder() {
|
||||
Some(self.rebind(trait_clause))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
|
||||
if let ty::Clause::Projection(projection_clause) = self.skip_binder() {
|
||||
Some(self.rebind(projection_clause))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum PredicateKind<'tcx> {
|
||||
@ -1203,6 +1221,17 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for TraitRef<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> {
|
||||
Binder::dummy(Clause::Trait(TraitPredicate {
|
||||
trait_ref: self,
|
||||
constness: ty::BoundConstness::NotConst,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
@ -1211,6 +1240,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> {
|
||||
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
|
||||
pred.to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
|
||||
@ -1240,6 +1277,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyTraitPredicate<'tcx> {
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> {
|
||||
self.map_bound(|p| Clause::Trait(p))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
|
||||
@ -1258,6 +1301,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyProjectionPredicate<'tcx> {
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> {
|
||||
self.map_bound(|p| Clause::Projection(p))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
|
||||
@ -1327,6 +1376,23 @@ impl<'tcx> Predicate<'tcx> {
|
||||
| PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_clause(self) -> Option<Binder<'tcx, Clause<'tcx>>> {
|
||||
let predicate = self.kind();
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Clause(clause) => Some(predicate.rebind(clause)),
|
||||
PredicateKind::AliasRelate(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
| PredicateKind::Coerce(..)
|
||||
| PredicateKind::WellFormed(..)
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::ClosureKind(..)
|
||||
| PredicateKind::ConstEvaluatable(..)
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous
|
||||
| PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the bounds declared on a particular set of type
|
||||
|
@ -15,6 +15,10 @@ pub struct CheckAlignment;
|
||||
|
||||
impl<'tcx> MirPass<'tcx> for CheckAlignment {
|
||||
fn is_enabled(&self, sess: &Session) -> bool {
|
||||
// FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows
|
||||
if sess.target.llvm_target == "i686-pc-windows-msvc" {
|
||||
return false;
|
||||
}
|
||||
sess.opts.debug_assertions
|
||||
}
|
||||
|
||||
|
@ -507,7 +507,7 @@ impl HygieneData {
|
||||
self.normalize_to_macro_rules(call_site_ctxt)
|
||||
};
|
||||
|
||||
if call_site_ctxt == SyntaxContext::root() {
|
||||
if call_site_ctxt.is_root() {
|
||||
return self.apply_mark_internal(ctxt, expn_id, transparency);
|
||||
}
|
||||
|
||||
@ -671,12 +671,17 @@ impl SyntaxContext {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn as_u32(self) -> u32 {
|
||||
pub const fn is_root(self) -> bool {
|
||||
self.0 == SyntaxContext::root().as_u32()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) const fn as_u32(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn from_u32(raw: u32) -> SyntaxContext {
|
||||
pub(crate) const fn from_u32(raw: u32) -> SyntaxContext {
|
||||
SyntaxContext(raw)
|
||||
}
|
||||
|
||||
@ -1500,7 +1505,7 @@ impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
|
||||
const TAG_EXPANSION: u8 = 0;
|
||||
const TAG_NO_EXPANSION: u8 = 1;
|
||||
|
||||
if *self == SyntaxContext::root() {
|
||||
if self.is_root() {
|
||||
TAG_NO_EXPANSION.hash_stable(ctx, hasher);
|
||||
} else {
|
||||
TAG_EXPANSION.hash_stable(ctx, hasher);
|
||||
|
@ -826,9 +826,9 @@ impl Span {
|
||||
// Return the macro span on its own to avoid weird diagnostic output. It is preferable to
|
||||
// have an incomplete span than a completely nonsensical one.
|
||||
if span_data.ctxt != end_data.ctxt {
|
||||
if span_data.ctxt == SyntaxContext::root() {
|
||||
if span_data.ctxt.is_root() {
|
||||
return end;
|
||||
} else if end_data.ctxt == SyntaxContext::root() {
|
||||
} else if end_data.ctxt.is_root() {
|
||||
return self;
|
||||
}
|
||||
// Both spans fall within a macro.
|
||||
@ -837,7 +837,7 @@ impl Span {
|
||||
Span::new(
|
||||
cmp::min(span_data.lo, end_data.lo),
|
||||
cmp::max(span_data.hi, end_data.hi),
|
||||
if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
|
||||
if span_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt },
|
||||
if span_data.parent == end_data.parent { span_data.parent } else { None },
|
||||
)
|
||||
}
|
||||
@ -855,7 +855,7 @@ impl Span {
|
||||
Span::new(
|
||||
span.hi,
|
||||
end.lo,
|
||||
if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
|
||||
if end.ctxt.is_root() { end.ctxt } else { span.ctxt },
|
||||
if span.parent == end.parent { span.parent } else { None },
|
||||
)
|
||||
}
|
||||
@ -879,9 +879,9 @@ impl Span {
|
||||
// Return the macro span on its own to avoid weird diagnostic output. It is preferable to
|
||||
// have an incomplete span than a completely nonsensical one.
|
||||
if span_data.ctxt != end_data.ctxt {
|
||||
if span_data.ctxt == SyntaxContext::root() {
|
||||
if span_data.ctxt.is_root() {
|
||||
return end;
|
||||
} else if end_data.ctxt == SyntaxContext::root() {
|
||||
} else if end_data.ctxt.is_root() {
|
||||
return self;
|
||||
}
|
||||
// Both spans fall within a macro.
|
||||
@ -890,7 +890,7 @@ impl Span {
|
||||
Span::new(
|
||||
span_data.lo,
|
||||
end_data.lo,
|
||||
if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
|
||||
if end_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt },
|
||||
if span_data.parent == end_data.parent { span_data.parent } else { None },
|
||||
)
|
||||
}
|
||||
|
@ -1156,6 +1156,7 @@ symbols! {
|
||||
ptr_null_mut,
|
||||
ptr_offset_from,
|
||||
ptr_offset_from_unsigned,
|
||||
ptr_unique,
|
||||
pub_macro_rules,
|
||||
pub_restricted,
|
||||
public,
|
||||
|
@ -105,7 +105,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Predicate<'tcx>,
|
||||
assumption: ty::Binder<'tcx, ty::Clause<'tcx>>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
) -> QueryResult<'tcx>;
|
||||
|
||||
@ -115,7 +115,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
fn consider_implied_clause(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Predicate<'tcx>,
|
||||
assumption: ty::Binder<'tcx, ty::Clause<'tcx>>,
|
||||
requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||
) -> QueryResult<'tcx> {
|
||||
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
|
||||
@ -131,7 +131,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
fn consider_alias_bound_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Predicate<'tcx>,
|
||||
assumption: ty::Binder<'tcx, ty::Clause<'tcx>>,
|
||||
) -> QueryResult<'tcx> {
|
||||
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
|
||||
ecx.validate_alias_bound_self_from_param_env(goal)
|
||||
@ -144,7 +144,7 @@ pub(super) trait GoalKind<'tcx>:
|
||||
fn consider_object_bound_candidate(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Predicate<'tcx>,
|
||||
assumption: ty::Binder<'tcx, ty::Clause<'tcx>>,
|
||||
) -> QueryResult<'tcx> {
|
||||
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
|
||||
let tcx = ecx.tcx();
|
||||
@ -467,11 +467,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
candidates: &mut Vec<Candidate<'tcx>>,
|
||||
) {
|
||||
for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
|
||||
match G::consider_implied_clause(self, goal, assumption, []) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
|
||||
if let Some(clause) = assumption.as_clause() {
|
||||
match G::consider_implied_clause(self, goal, clause, []) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -517,11 +519,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
|
||||
for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
|
||||
{
|
||||
match G::consider_alias_bound_candidate(self, goal, assumption) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::AliasBound, result })
|
||||
if let Some(clause) = assumption.as_clause() {
|
||||
match G::consider_alias_bound_candidate(self, goal, clause) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::AliasBound, result })
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -675,18 +679,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
// projection predicates that we reach by elaborating the principal trait ref,
|
||||
// since that'll cause ambiguity.
|
||||
//
|
||||
// We can remove this when we have implemented intersections in responses.
|
||||
// We can remove this when we have implemented lifetime intersections in responses.
|
||||
if assumption.to_opt_poly_projection_pred().is_some()
|
||||
&& !own_bounds.contains(&assumption)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
match G::consider_object_bound_candidate(self, goal, assumption) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
|
||||
if let Some(clause) = assumption.as_clause() {
|
||||
match G::consider_object_bound_candidate(self, goal, clause) {
|
||||
Ok(result) => {
|
||||
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
Err(NoSolution) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,15 +105,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Predicate<'tcx>,
|
||||
assumption: ty::Binder<'tcx, ty::Clause<'tcx>>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
) -> QueryResult<'tcx> {
|
||||
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
|
||||
&& poly_projection_pred.projection_def_id() == goal.predicate.def_id()
|
||||
if let Some(projection_pred) = assumption.as_projection_clause()
|
||||
&& projection_pred.projection_def_id() == goal.predicate.def_id()
|
||||
{
|
||||
ecx.probe(|ecx| {
|
||||
let assumption_projection_pred =
|
||||
ecx.instantiate_binder_with_infer(poly_projection_pred);
|
||||
ecx.instantiate_binder_with_infer(projection_pred);
|
||||
ecx.eq(
|
||||
goal.param_env,
|
||||
goal.predicate.projection_ty,
|
||||
|
@ -81,17 +81,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
fn probe_and_match_goal_against_assumption(
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
assumption: ty::Predicate<'tcx>,
|
||||
assumption: ty::Binder<'tcx, ty::Clause<'tcx>>,
|
||||
then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
|
||||
) -> QueryResult<'tcx> {
|
||||
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
|
||||
&& poly_trait_pred.def_id() == goal.predicate.def_id()
|
||||
&& poly_trait_pred.polarity() == goal.predicate.polarity
|
||||
if let Some(trait_clause) = assumption.as_trait_clause()
|
||||
&& trait_clause.def_id() == goal.predicate.def_id()
|
||||
&& trait_clause.polarity() == goal.predicate.polarity
|
||||
{
|
||||
// FIXME: Constness
|
||||
ecx.probe(|ecx| {
|
||||
let assumption_trait_pred =
|
||||
ecx.instantiate_binder_with_infer(poly_trait_pred);
|
||||
ecx.instantiate_binder_with_infer(trait_clause);
|
||||
ecx.eq(
|
||||
goal.param_env,
|
||||
goal.predicate.trait_ref,
|
||||
|
@ -32,6 +32,8 @@ use crate::ptr::NonNull;
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
#[repr(transparent)]
|
||||
// Lang item used experimentally by Miri to define the semantics of `Unique`.
|
||||
#[cfg_attr(not(bootstrap), lang = "ptr_unique")]
|
||||
pub struct Unique<T: ?Sized> {
|
||||
pointer: NonNull<T>,
|
||||
// NOTE: this marker has no consequences for variance, but is necessary
|
||||
|
@ -47,9 +47,9 @@ use buffer::Buffer;
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufReader<R> {
|
||||
inner: R,
|
||||
pub struct BufReader<R: ?Sized> {
|
||||
buf: Buffer,
|
||||
inner: R,
|
||||
}
|
||||
|
||||
impl<R: Read> BufReader<R> {
|
||||
@ -95,7 +95,7 @@ impl<R: Read> BufReader<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> BufReader<R> {
|
||||
impl<R: ?Sized> BufReader<R> {
|
||||
/// Gets a reference to the underlying reader.
|
||||
///
|
||||
/// It is inadvisable to directly read from the underlying reader.
|
||||
@ -213,7 +213,10 @@ impl<R> BufReader<R> {
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(self) -> R {
|
||||
pub fn into_inner(self) -> R
|
||||
where
|
||||
R: Sized,
|
||||
{
|
||||
self.inner
|
||||
}
|
||||
|
||||
@ -226,13 +229,13 @@ impl<R> BufReader<R> {
|
||||
|
||||
// This is only used by a test which asserts that the initialization-tracking is correct.
|
||||
#[cfg(test)]
|
||||
impl<R> BufReader<R> {
|
||||
impl<R: ?Sized> BufReader<R> {
|
||||
pub fn initialized(&self) -> usize {
|
||||
self.buf.initialized()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Seek> BufReader<R> {
|
||||
impl<R: ?Sized + Seek> BufReader<R> {
|
||||
/// Seeks relative to the current position. If the new position lies within the buffer,
|
||||
/// the buffer will not be flushed, allowing for more efficient seeks.
|
||||
/// This method does not return the location of the underlying reader, so the caller
|
||||
@ -257,7 +260,7 @@ impl<R: Seek> BufReader<R> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Read> Read for BufReader<R> {
|
||||
impl<R: ?Sized + Read> Read for BufReader<R> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
// If we don't have any buffered data and we're doing a massive read
|
||||
// (larger than our internal buffer), bypass our internal buffer
|
||||
@ -371,7 +374,7 @@ impl<R: Read> Read for BufReader<R> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Read> BufRead for BufReader<R> {
|
||||
impl<R: ?Sized + Read> BufRead for BufReader<R> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
self.buf.fill_buf(&mut self.inner)
|
||||
}
|
||||
@ -384,11 +387,11 @@ impl<R: Read> BufRead for BufReader<R> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R> fmt::Debug for BufReader<R>
|
||||
where
|
||||
R: fmt::Debug,
|
||||
R: ?Sized + fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("BufReader")
|
||||
.field("reader", &self.inner)
|
||||
.field("reader", &&self.inner)
|
||||
.field(
|
||||
"buffer",
|
||||
&format_args!("{}/{}", self.buf.filled() - self.buf.pos(), self.capacity()),
|
||||
@ -398,7 +401,7 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<R: Seek> Seek for BufReader<R> {
|
||||
impl<R: ?Sized + Seek> Seek for BufReader<R> {
|
||||
/// Seek to an offset, in bytes, in the underlying reader.
|
||||
///
|
||||
/// The position used for seeking with <code>[SeekFrom::Current]\(_)</code> is the
|
||||
@ -491,7 +494,7 @@ impl<R: Seek> Seek for BufReader<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SizeHint for BufReader<T> {
|
||||
impl<T: ?Sized> SizeHint for BufReader<T> {
|
||||
#[inline]
|
||||
fn lower_bound(&self) -> usize {
|
||||
SizeHint::lower_bound(self.get_ref()) + self.buffer().len()
|
||||
|
@ -67,8 +67,7 @@ use crate::ptr;
|
||||
/// [`TcpStream`]: crate::net::TcpStream
|
||||
/// [`flush`]: BufWriter::flush
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BufWriter<W: Write> {
|
||||
inner: W,
|
||||
pub struct BufWriter<W: ?Sized + Write> {
|
||||
// The buffer. Avoid using this like a normal `Vec` in common code paths.
|
||||
// That is, don't use `buf.push`, `buf.extend_from_slice`, or any other
|
||||
// methods that require bounds checking or the like. This makes an enormous
|
||||
@ -78,6 +77,7 @@ pub struct BufWriter<W: Write> {
|
||||
// write the buffered data a second time in BufWriter's destructor. This
|
||||
// flag tells the Drop impl if it should skip the flush.
|
||||
panicked: bool,
|
||||
inner: W,
|
||||
}
|
||||
|
||||
impl<W: Write> BufWriter<W> {
|
||||
@ -115,6 +115,69 @@ impl<W: Write> BufWriter<W> {
|
||||
BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false }
|
||||
}
|
||||
|
||||
/// Unwraps this `BufWriter<W>`, returning the underlying writer.
|
||||
///
|
||||
/// The buffer is written out before returning the writer.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // unwrap the TcpStream and flush the buffer
|
||||
/// let stream = buffer.into_inner().unwrap();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
|
||||
match self.flush_buf() {
|
||||
Err(e) => Err(IntoInnerError::new(self, e)),
|
||||
Ok(()) => Ok(self.into_parts().0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
|
||||
/// unwritten data.
|
||||
///
|
||||
/// If the underlying writer panicked, it is not known what portion of the data was written.
|
||||
/// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
|
||||
/// contents can still be recovered).
|
||||
///
|
||||
/// `into_parts` makes no attempt to flush data and cannot fail.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{BufWriter, Write};
|
||||
///
|
||||
/// let mut buffer = [0u8; 10];
|
||||
/// let mut stream = BufWriter::new(buffer.as_mut());
|
||||
/// write!(stream, "too much data").unwrap();
|
||||
/// stream.flush().expect_err("it doesn't fit");
|
||||
/// let (recovered_writer, buffered_data) = stream.into_parts();
|
||||
/// assert_eq!(recovered_writer.len(), 0);
|
||||
/// assert_eq!(&buffered_data.unwrap(), b"ata");
|
||||
/// ```
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
|
||||
let buf = mem::take(&mut self.buf);
|
||||
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
|
||||
|
||||
// SAFETY: forget(self) prevents double dropping inner
|
||||
let inner = unsafe { ptr::read(&self.inner) };
|
||||
mem::forget(self);
|
||||
|
||||
(inner, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Write> BufWriter<W> {
|
||||
/// Send data in our local buffer into the inner writer, looping as
|
||||
/// necessary until either it's all been sent or an error occurs.
|
||||
///
|
||||
@ -284,67 +347,6 @@ impl<W: Write> BufWriter<W> {
|
||||
self.buf.capacity()
|
||||
}
|
||||
|
||||
/// Unwraps this `BufWriter<W>`, returning the underlying writer.
|
||||
///
|
||||
/// The buffer is written out before returning the writer.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
|
||||
///
|
||||
/// // unwrap the TcpStream and flush the buffer
|
||||
/// let stream = buffer.into_inner().unwrap();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
|
||||
match self.flush_buf() {
|
||||
Err(e) => Err(IntoInnerError::new(self, e)),
|
||||
Ok(()) => Ok(self.into_parts().0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Disassembles this `BufWriter<W>`, returning the underlying writer, and any buffered but
|
||||
/// unwritten data.
|
||||
///
|
||||
/// If the underlying writer panicked, it is not known what portion of the data was written.
|
||||
/// In this case, we return `WriterPanicked` for the buffered data (from which the buffer
|
||||
/// contents can still be recovered).
|
||||
///
|
||||
/// `into_parts` makes no attempt to flush data and cannot fail.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{BufWriter, Write};
|
||||
///
|
||||
/// let mut buffer = [0u8; 10];
|
||||
/// let mut stream = BufWriter::new(buffer.as_mut());
|
||||
/// write!(stream, "too much data").unwrap();
|
||||
/// stream.flush().expect_err("it doesn't fit");
|
||||
/// let (recovered_writer, buffered_data) = stream.into_parts();
|
||||
/// assert_eq!(recovered_writer.len(), 0);
|
||||
/// assert_eq!(&buffered_data.unwrap(), b"ata");
|
||||
/// ```
|
||||
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
|
||||
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
|
||||
let buf = mem::take(&mut self.buf);
|
||||
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
|
||||
|
||||
// SAFETY: forget(self) prevents double dropping inner
|
||||
let inner = unsafe { ptr::read(&self.inner) };
|
||||
mem::forget(self);
|
||||
|
||||
(inner, buf)
|
||||
}
|
||||
|
||||
// Ensure this function does not get inlined into `write`, so that it
|
||||
// remains inlineable and its common path remains as short as possible.
|
||||
// If this function ends up being called frequently relative to `write`,
|
||||
@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Write for BufWriter<W> {
|
||||
impl<W: ?Sized + Write> Write for BufWriter<W> {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
// Use < instead of <= to avoid a needless trip through the buffer in some cases.
|
||||
@ -640,20 +642,20 @@ impl<W: Write> Write for BufWriter<W> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> fmt::Debug for BufWriter<W>
|
||||
impl<W: ?Sized + Write> fmt::Debug for BufWriter<W>
|
||||
where
|
||||
W: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("BufWriter")
|
||||
.field("writer", &self.inner)
|
||||
.field("writer", &&self.inner)
|
||||
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write + Seek> Seek for BufWriter<W> {
|
||||
impl<W: ?Sized + Write + Seek> Seek for BufWriter<W> {
|
||||
/// Seek to the offset, in bytes, in the underlying writer.
|
||||
///
|
||||
/// Seeking always writes out the internal buffer before seeking.
|
||||
@ -664,7 +666,7 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Drop for BufWriter<W> {
|
||||
impl<W: ?Sized + Write> Drop for BufWriter<W> {
|
||||
fn drop(&mut self) {
|
||||
if !self.panicked {
|
||||
// dtors should not panic, so we ignore a failed flush
|
||||
|
@ -64,7 +64,7 @@ use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSli
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct LineWriter<W: Write> {
|
||||
pub struct LineWriter<W: ?Sized + Write> {
|
||||
inner: BufWriter<W>,
|
||||
}
|
||||
|
||||
@ -109,27 +109,6 @@ impl<W: Write> LineWriter<W> {
|
||||
LineWriter { inner: BufWriter::with_capacity(capacity, inner) }
|
||||
}
|
||||
|
||||
/// Gets a reference to the underlying writer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let file = LineWriter::new(file);
|
||||
///
|
||||
/// let reference = file.get_ref();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &W {
|
||||
self.inner.get_ref()
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the underlying writer.
|
||||
///
|
||||
/// Caution must be taken when calling methods on the mutable reference
|
||||
@ -184,8 +163,31 @@ impl<W: Write> LineWriter<W> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: ?Sized + Write> LineWriter<W> {
|
||||
/// Gets a reference to the underlying writer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs::File;
|
||||
/// use std::io::LineWriter;
|
||||
///
|
||||
/// fn main() -> std::io::Result<()> {
|
||||
/// let file = File::create("poem.txt")?;
|
||||
/// let file = LineWriter::new(file);
|
||||
///
|
||||
/// let reference = file.get_ref();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_ref(&self) -> &W {
|
||||
self.inner.get_ref()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> Write for LineWriter<W> {
|
||||
impl<W: ?Sized + Write> Write for LineWriter<W> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
LineWriterShim::new(&mut self.inner).write(buf)
|
||||
}
|
||||
@ -216,7 +218,7 @@ impl<W: Write> Write for LineWriter<W> {
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<W: Write> fmt::Debug for LineWriter<W>
|
||||
impl<W: ?Sized + Write> fmt::Debug for LineWriter<W>
|
||||
where
|
||||
W: fmt::Debug,
|
||||
{
|
||||
|
@ -11,11 +11,11 @@ use crate::sys_common::memchr;
|
||||
/// `BufWriters` to be temporarily given line-buffering logic; this is what
|
||||
/// enables Stdout to be alternately in line-buffered or block-buffered mode.
|
||||
#[derive(Debug)]
|
||||
pub struct LineWriterShim<'a, W: Write> {
|
||||
pub struct LineWriterShim<'a, W: ?Sized + Write> {
|
||||
buffer: &'a mut BufWriter<W>,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> LineWriterShim<'a, W> {
|
||||
impl<'a, W: ?Sized + Write> LineWriterShim<'a, W> {
|
||||
pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
|
||||
Self { buffer }
|
||||
}
|
||||
@ -49,7 +49,7 @@ impl<'a, W: Write> LineWriterShim<'a, W> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Write for LineWriterShim<'a, W> {
|
||||
impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> {
|
||||
/// Write some data into this BufReader with line buffering. This means
|
||||
/// that, if any newlines are present in the data, the data up to the last
|
||||
/// newline is sent directly to the underlying writer, and data after it
|
||||
|
@ -86,7 +86,7 @@ impl<W: Write + ?Sized> BufferedCopySpec for W {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Write> BufferedCopySpec for BufWriter<I> {
|
||||
impl<I: ?Sized + Write> BufferedCopySpec for BufWriter<I> {
|
||||
fn copy_to<R: Read + ?Sized>(reader: &mut R, writer: &mut Self) -> Result<u64> {
|
||||
if writer.capacity() < DEFAULT_BUF_SIZE {
|
||||
return stack_buffer_copy(reader, writer);
|
||||
|
@ -2754,7 +2754,7 @@ trait SizeHint {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SizeHint for T {
|
||||
impl<T: ?Sized> SizeHint for T {
|
||||
#[inline]
|
||||
default fn lower_bound(&self) -> usize {
|
||||
0
|
||||
|
@ -466,7 +466,7 @@ impl<T: CopyRead> CopyRead for Take<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CopyRead> CopyRead for BufReader<T> {
|
||||
impl<T: ?Sized + CopyRead> CopyRead for BufReader<T> {
|
||||
fn drain_to<W: Write>(&mut self, writer: &mut W, outer_limit: u64) -> Result<u64> {
|
||||
let buf = self.buffer();
|
||||
let buf = &buf[0..min(buf.len(), outer_limit.try_into().unwrap_or(usize::MAX))];
|
||||
@ -495,7 +495,7 @@ impl<T: CopyRead> CopyRead for BufReader<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: CopyWrite> CopyWrite for BufWriter<T> {
|
||||
impl<T: ?Sized + CopyWrite> CopyWrite for BufWriter<T> {
|
||||
fn properties(&self) -> CopyParams {
|
||||
self.get_ref().properties()
|
||||
}
|
||||
|
@ -344,6 +344,29 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "netbsd")]
|
||||
{
|
||||
unsafe {
|
||||
let set = libc::_cpuset_create();
|
||||
if !set.is_null() {
|
||||
let mut count: usize = 0;
|
||||
if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
|
||||
for i in 0..u64::MAX {
|
||||
match libc::_cpuset_isset(i, set) {
|
||||
-1 => break,
|
||||
0 => continue,
|
||||
_ => count = count + 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
libc::_cpuset_destroy(set);
|
||||
if let Some(count) = NonZeroUsize::new(count) {
|
||||
return Ok(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut cpus: libc::c_uint = 0;
|
||||
let mut cpus_size = crate::mem::size_of_val(&cpus);
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
|
||||
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}size: 32,{{.*}}
|
||||
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i64 4294967295{{[,)].*}}
|
||||
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i64 0{{[,)].*}}
|
||||
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i128 4294967295{{[,)].*}}
|
||||
// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i128 0{{[,)].*}}
|
||||
|
||||
#![feature(never_type)]
|
||||
|
||||
|
27
tests/codegen/enum-u128.rs
Normal file
27
tests/codegen/enum-u128.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// This tests that debug info for "c-like" 128bit enums is properly emitted.
|
||||
// This is ignored for the fallback mode on MSVC due to problems with PDB.
|
||||
|
||||
//
|
||||
// ignore-msvc
|
||||
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
|
||||
// CHECK-LABEL: @main
|
||||
// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "Foo",{{.*}}flags: DIFlagEnumClass,{{.*}}
|
||||
// CHECK: {{.*}}DIEnumerator{{.*}}name: "Lo",{{.*}}value: 0,{{.*}}
|
||||
// CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}}
|
||||
// CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}}
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(repr128)]
|
||||
|
||||
#[repr(u128)]
|
||||
pub enum Foo {
|
||||
Lo,
|
||||
Hi = 1 << 64,
|
||||
Bar = 18_446_745_000_000_000_123,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let foo = Foo::Bar;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
// run-fail
|
||||
// ignore-wasm32-bare: No panic messages
|
||||
// ignore-i686-pc-windows-msvc: #112480
|
||||
// compile-flags: -C debug-assertions
|
||||
// error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
|
||||
|
||||
|
21
tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs
Normal file
21
tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// run-pass
|
||||
// only-i686-pc-windows-msvc
|
||||
// compile-flags: -Copt-level=0 -Cdebug-assertions=yes
|
||||
|
||||
// MSVC isn't sure if on 32-bit Windows its u64 type is 8-byte-aligned or 4-byte-aligned.
|
||||
// So this test ensures that on i686-pc-windows-msvc, we do not insert a runtime check
|
||||
// that will fail on dereferencing of a pointer to u64 which is not 8-byte-aligned but is
|
||||
// 4-byte-aligned.
|
||||
|
||||
#![feature(strict_provenance)]
|
||||
|
||||
fn main() {
|
||||
let mut x = [0u64; 2];
|
||||
let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
|
||||
unsafe {
|
||||
let misaligned = ptr.add(4).cast::<u64>();
|
||||
assert!(misaligned.addr() % 8 != 0);
|
||||
assert!(misaligned.addr() % 4 == 0);
|
||||
*misaligned = 42;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user