mirror of https://github.com/rust-lang/rust.git
Auto merge of #120401 - matthiaskrgr:rollup-7740vrx, r=matthiaskrgr
Rollup of 12 pull requests Successful merges: - #103522 (stabilise array methods) - #113489 (impl `From<&[T; N]>` for `Cow<[T]>`) - #119342 (Emit suggestion when trying to write exclusive ranges as `..<`) - #119562 (Rename `pointer` field on `Pin`) - #119800 (Document `rustc_index::vec::IndexVec`) - #120205 (std: make `HEAP` initializer never inline) - #120277 (Normalize field types before checking validity) - #120311 (core: add `From<core::ascii::Char>` implementations) - #120366 (mark a doctest with UB as no_run) - #120378 (always normalize `LoweredTy` in the new solver) - #120382 (Classify closure arguments in refutable pattern in argument error) - #120389 (Add fmease to the compiler review rotation) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
b362939be1
|
@ -810,13 +810,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
let adt_def = self.tcx.adt_def(def_id);
|
||||
assert!(adt_def.is_union());
|
||||
assert_eq!(idx, FIRST_VARIANT);
|
||||
let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
|
||||
if fields.len() != 1 {
|
||||
self.fail(location, "unions should have one initialized field");
|
||||
}
|
||||
if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
|
||||
let dest_ty = self.tcx.normalize_erasing_regions(
|
||||
self.param_env,
|
||||
adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
|
||||
);
|
||||
if fields.len() == 1 {
|
||||
let src_ty = fields.raw[0].ty(self.body, self.tcx);
|
||||
if !self.mir_assign_valid_types(src_ty, dest_ty) {
|
||||
self.fail(location, "union field has the wrong type");
|
||||
}
|
||||
} else {
|
||||
self.fail(location, "unions should have one initialized field");
|
||||
}
|
||||
}
|
||||
AggregateKind::Adt(def_id, idx, args, _, None) => {
|
||||
let adt_def = self.tcx.adt_def(def_id);
|
||||
|
@ -826,10 +831,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
self.fail(location, "adt has the wrong number of initialized fields");
|
||||
}
|
||||
for (src, dest) in std::iter::zip(fields, &variant.fields) {
|
||||
if !self.mir_assign_valid_types(
|
||||
src.ty(self.body, self.tcx),
|
||||
dest.ty(self.tcx, args),
|
||||
) {
|
||||
let dest_ty = self
|
||||
.tcx
|
||||
.normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
|
||||
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
|
||||
self.fail(location, "adt field has the wrong type");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -369,6 +369,14 @@ pub struct LoweredTy<'tcx> {
|
|||
|
||||
impl<'tcx> LoweredTy<'tcx> {
|
||||
pub fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> {
|
||||
LoweredTy { raw, normalized: fcx.normalize(span, raw) }
|
||||
// FIXME(-Znext-solver): We're still figuring out how to best handle
|
||||
// normalization and this doesn't feel too great. We should look at this
|
||||
// code again before stabilizing it.
|
||||
let normalized = if fcx.next_trait_solver() {
|
||||
fcx.try_structurally_resolve_type(span, raw)
|
||||
} else {
|
||||
fcx.normalize(span, raw)
|
||||
};
|
||||
LoweredTy { raw, normalized }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2040,7 +2040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let field_is_local = sole_field.did.is_local();
|
||||
let field_is_accessible =
|
||||
sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
|
||||
// Skip suggestions for unstable public fields (for example `Pin::pointer`)
|
||||
// Skip suggestions for unstable public fields (for example `Pin::__pointer`)
|
||||
&& matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked);
|
||||
|
||||
if !field_is_local && !field_is_accessible {
|
||||
|
|
|
@ -12,10 +12,13 @@ use std::vec;
|
|||
use crate::{Idx, IndexSlice};
|
||||
|
||||
/// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`.
|
||||
/// Its purpose is to avoid mixing indexes.
|
||||
///
|
||||
/// While it's possible to use `u32` or `usize` directly for `I`,
|
||||
/// you almost certainly want to use a [`newtype_index!`]-generated type instead.
|
||||
///
|
||||
/// This allows to index the IndexVec with the new index type.
|
||||
///
|
||||
/// [`newtype_index!`]: ../macro.newtype_index.html
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
|
@ -25,11 +28,13 @@ pub struct IndexVec<I: Idx, T> {
|
|||
}
|
||||
|
||||
impl<I: Idx, T> IndexVec<I, T> {
|
||||
/// Constructs a new, empty `IndexVec<I, T>`.
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
IndexVec::from_raw(Vec::new())
|
||||
}
|
||||
|
||||
/// Constructs a new `IndexVec<I, T>` from a `Vec<T>`.
|
||||
#[inline]
|
||||
pub const fn from_raw(raw: Vec<T>) -> Self {
|
||||
IndexVec { raw, _marker: PhantomData }
|
||||
|
@ -59,6 +64,7 @@ impl<I: Idx, T> IndexVec<I, T> {
|
|||
IndexVec::from_raw(vec![elem; universe.len()])
|
||||
}
|
||||
|
||||
/// Creates a new IndexVec with n copies of the `elem`.
|
||||
#[inline]
|
||||
pub fn from_elem_n(elem: T, n: usize) -> Self
|
||||
where
|
||||
|
@ -85,6 +91,7 @@ impl<I: Idx, T> IndexVec<I, T> {
|
|||
IndexSlice::from_raw_mut(&mut self.raw)
|
||||
}
|
||||
|
||||
/// Pushes an element to the array returning the index where it was pushed to.
|
||||
#[inline]
|
||||
pub fn push(&mut self, d: T) -> I {
|
||||
let idx = self.next_index();
|
||||
|
|
|
@ -47,9 +47,18 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
|
|||
};
|
||||
visitor.visit_expr(&thir[expr]);
|
||||
|
||||
let origin = match tcx.def_kind(def_id) {
|
||||
DefKind::AssocFn | DefKind::Fn => "function argument",
|
||||
DefKind::Closure => "closure argument",
|
||||
// other types of MIR don't have function parameters, and we don't need to
|
||||
// categorize those for the irrefutable check.
|
||||
_ if thir.params.is_empty() => "",
|
||||
kind => bug!("unexpected function parameters in THIR: {kind:?} {def_id:?}"),
|
||||
};
|
||||
|
||||
for param in thir.params.iter() {
|
||||
if let Some(box ref pattern) = param.pat {
|
||||
visitor.check_binding_is_irrefutable(pattern, "function argument", None, None);
|
||||
visitor.check_binding_is_irrefutable(pattern, origin, None, None);
|
||||
}
|
||||
}
|
||||
visitor.error
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::parser;
|
|||
use crate::parser::attr::InnerAttrPolicy;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
|
||||
use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::AttrTokenTree;
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
use rustc_ast::{
|
||||
|
@ -448,12 +448,11 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
let mut expected = edible
|
||||
self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token));
|
||||
let mut expected = self
|
||||
.expected_tokens
|
||||
.iter()
|
||||
.chain(inedible)
|
||||
.cloned()
|
||||
.map(TokenType::Token)
|
||||
.chain(self.expected_tokens.iter().cloned())
|
||||
.filter(|token| {
|
||||
// Filter out suggestions that suggest the same token which was found and deemed incorrect.
|
||||
fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
|
||||
|
@ -2927,6 +2926,22 @@ impl<'a> Parser<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Check for exclusive ranges written as `..<`
|
||||
pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> {
|
||||
if maybe_lt == token::Lt
|
||||
&& (self.expected_tokens.contains(&TokenType::Token(token::Gt))
|
||||
|| matches!(self.token.kind, token::Literal(..)))
|
||||
{
|
||||
err.span_suggestion(
|
||||
maybe_lt.span,
|
||||
"remove the `<` to write an exclusive range",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
err
|
||||
}
|
||||
|
||||
pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
|
||||
(0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
|
||||
&& self.look_ahead(3, |tok| tok == short_kind)
|
||||
|
|
|
@ -482,7 +482,11 @@ impl<'a> Parser<'a> {
|
|||
cur_op_span: Span,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
let rhs = if self.is_at_start_of_range_notation_rhs() {
|
||||
Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
|
||||
let maybe_lt = self.token.clone();
|
||||
Some(
|
||||
self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)
|
||||
.map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -531,11 +535,13 @@ impl<'a> Parser<'a> {
|
|||
let attrs = self.parse_or_use_outer_attributes(attrs)?;
|
||||
self.collect_tokens_for_expr(attrs, |this, attrs| {
|
||||
let lo = this.token.span;
|
||||
let maybe_lt = this.look_ahead(1, |t| t.clone());
|
||||
this.bump();
|
||||
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
|
||||
// RHS must be parsed with more associativity than the dots.
|
||||
this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
|
||||
.map(|x| (lo.to(x.span), Some(x)))?
|
||||
.map(|x| (lo.to(x.span), Some(x)))
|
||||
.map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
|
||||
} else {
|
||||
(lo, None)
|
||||
};
|
||||
|
|
|
@ -103,7 +103,6 @@
|
|||
#![feature(allocator_api)]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(array_into_iter_constructors)]
|
||||
#![feature(array_methods)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(ascii_char)]
|
||||
#![feature(assert_matches)]
|
||||
|
|
|
@ -15,6 +15,19 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
|
|||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> {
|
||||
/// Creates a [`Borrowed`] variant of [`Cow`]
|
||||
/// from a reference to an array.
|
||||
///
|
||||
/// This conversion does not allocate or clone the data.
|
||||
///
|
||||
/// [`Borrowed`]: crate::borrow::Cow::Borrowed
|
||||
fn from(s: &'a [T; N]) -> Cow<'a, [T]> {
|
||||
Cow::Borrowed(s as &[_])
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "cow_from_vec", since = "1.8.0")]
|
||||
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
|
||||
/// Creates an [`Owned`] variant of [`Cow`]
|
||||
|
|
|
@ -559,8 +559,6 @@ impl<T, const N: usize> [T; N] {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_methods)]
|
||||
///
|
||||
/// let floats = [3.1, 2.7, -1.0];
|
||||
/// let float_refs: [&f64; 3] = floats.each_ref();
|
||||
/// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
|
||||
|
@ -571,8 +569,6 @@ impl<T, const N: usize> [T; N] {
|
|||
/// array if its elements are not [`Copy`].
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_methods)]
|
||||
///
|
||||
/// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
|
||||
/// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
|
||||
/// assert_eq!(is_ascii, [true, false, true]);
|
||||
|
@ -580,7 +576,7 @@ impl<T, const N: usize> [T; N] {
|
|||
/// // We can still access the original array: it has not been moved.
|
||||
/// assert_eq!(strings.len(), 3);
|
||||
/// ```
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
#[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn each_ref(&self) -> [&T; N] {
|
||||
from_trusted_iterator(self.iter())
|
||||
}
|
||||
|
@ -592,7 +588,6 @@ impl<T, const N: usize> [T; N] {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(array_methods)]
|
||||
///
|
||||
/// let mut floats = [3.1, 2.7, -1.0];
|
||||
/// let float_refs: [&mut f64; 3] = floats.each_mut();
|
||||
|
@ -600,7 +595,7 @@ impl<T, const N: usize> [T; N] {
|
|||
/// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
|
||||
/// assert_eq!(floats, [0.0, 2.7, -1.0]);
|
||||
/// ```
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
#[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn each_mut(&mut self) -> [&mut T; N] {
|
||||
from_trusted_iterator(self.iter_mut())
|
||||
}
|
||||
|
|
|
@ -537,6 +537,22 @@ impl AsciiChar {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! into_int_impl {
|
||||
($($ty:ty)*) => {
|
||||
$(
|
||||
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||
impl From<AsciiChar> for $ty {
|
||||
#[inline]
|
||||
fn from(chr: AsciiChar) -> $ty {
|
||||
chr as u8 as $ty
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
into_int_impl!(u8 u16 u32 u64 u128 char);
|
||||
|
||||
impl [AsciiChar] {
|
||||
/// Views this slice of ASCII characters as a UTF-8 `str`.
|
||||
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||
|
|
|
@ -2531,7 +2531,7 @@ extern "rust-intrinsic" {
|
|||
/// or `false`, and the caller has to ensure sound behavior for both cases.
|
||||
/// In other words, the following code has *Undefined Behavior*:
|
||||
///
|
||||
/// ```
|
||||
/// ```no_run
|
||||
/// #![feature(is_val_statically_known)]
|
||||
/// #![feature(core_intrinsics)]
|
||||
/// # #![allow(internal_features)]
|
||||
|
|
|
@ -1092,14 +1092,20 @@ pub struct Pin<Ptr> {
|
|||
// - deter downstream users from accessing it (which would be unsound!),
|
||||
// - let the `pin!` macro access it (such a macro requires using struct
|
||||
// literal syntax in order to benefit from lifetime extension).
|
||||
// Long-term, `unsafe` fields or macro hygiene are expected to offer more robust alternatives.
|
||||
//
|
||||
// However, if the `Deref` impl exposes a field with the same name as this
|
||||
// field, then the two will collide, resulting in a confusing error when the
|
||||
// user attempts to access the field through a `Pin<Ptr>`. Therefore, the
|
||||
// name `__pointer` is designed to be unlikely to collide with any other
|
||||
// field. Long-term, macro hygiene is expected to offer a more robust
|
||||
// alternative, alongside `unsafe` fields.
|
||||
#[unstable(feature = "unsafe_pin_internals", issue = "none")]
|
||||
#[doc(hidden)]
|
||||
pub pointer: Ptr,
|
||||
pub __pointer: Ptr,
|
||||
}
|
||||
|
||||
// The following implementations aren't derived in order to avoid soundness
|
||||
// issues. `&self.pointer` should not be accessible to untrusted trait
|
||||
// issues. `&self.__pointer` should not be accessible to untrusted trait
|
||||
// implementations.
|
||||
//
|
||||
// See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
|
||||
|
@ -1212,7 +1218,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
|
|||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
||||
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
||||
pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
|
||||
pin.pointer
|
||||
pin.__pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1349,7 +1355,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
|
||||
Pin { pointer }
|
||||
Pin { __pointer: pointer }
|
||||
}
|
||||
|
||||
/// Gets a shared reference to the pinned value this [`Pin`] points to.
|
||||
|
@ -1363,7 +1369,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||
#[inline(always)]
|
||||
pub fn as_ref(&self) -> Pin<&Ptr::Target> {
|
||||
// SAFETY: see documentation on this function
|
||||
unsafe { Pin::new_unchecked(&*self.pointer) }
|
||||
unsafe { Pin::new_unchecked(&*self.__pointer) }
|
||||
}
|
||||
|
||||
/// Unwraps this `Pin<Ptr>`, returning the underlying `Ptr`.
|
||||
|
@ -1388,7 +1394,7 @@ impl<Ptr: Deref> Pin<Ptr> {
|
|||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
||||
#[stable(feature = "pin_into_inner", since = "1.39.0")]
|
||||
pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
|
||||
pin.pointer
|
||||
pin.__pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1426,7 +1432,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
|
|||
#[inline(always)]
|
||||
pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
|
||||
// SAFETY: see documentation on this function
|
||||
unsafe { Pin::new_unchecked(&mut *self.pointer) }
|
||||
unsafe { Pin::new_unchecked(&mut *self.__pointer) }
|
||||
}
|
||||
|
||||
/// Assigns a new value to the memory location pointed to by the `Pin<Ptr>`.
|
||||
|
@ -1455,7 +1461,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
|
|||
where
|
||||
Ptr::Target: Sized,
|
||||
{
|
||||
*(self.pointer) = value;
|
||||
*(self.__pointer) = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1481,7 +1487,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
|
|||
U: ?Sized,
|
||||
F: FnOnce(&T) -> &U,
|
||||
{
|
||||
let pointer = &*self.pointer;
|
||||
let pointer = &*self.__pointer;
|
||||
let new_pointer = func(pointer);
|
||||
|
||||
// SAFETY: the safety contract for `new_unchecked` must be
|
||||
|
@ -1511,7 +1517,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
|
|||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub const fn get_ref(self) -> &'a T {
|
||||
self.pointer
|
||||
self.__pointer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1522,7 +1528,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
pub const fn into_ref(self) -> Pin<&'a T> {
|
||||
Pin { pointer: self.pointer }
|
||||
Pin { __pointer: self.__pointer }
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the data inside of this `Pin`.
|
||||
|
@ -1542,7 +1548,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||
where
|
||||
T: Unpin,
|
||||
{
|
||||
self.pointer
|
||||
self.__pointer
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the data inside of this `Pin`.
|
||||
|
@ -1560,7 +1566,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
|
||||
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
|
||||
self.pointer
|
||||
self.__pointer
|
||||
}
|
||||
|
||||
/// Construct a new pin by mapping the interior value.
|
||||
|
@ -1684,21 +1690,21 @@ impl<Ptr: Receiver> Receiver for Pin<Ptr> {}
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Debug> fmt::Debug for Pin<Ptr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.pointer, f)
|
||||
fmt::Debug::fmt(&self.__pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Display> fmt::Display for Pin<Ptr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.pointer, f)
|
||||
fmt::Display::fmt(&self.__pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.pointer, f)
|
||||
fmt::Pointer::fmt(&self.__pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1941,16 +1947,16 @@ pub macro pin($value:expr $(,)?) {
|
|||
// instead, dropped _at the end of the enscoping block_.
|
||||
// For instance,
|
||||
// ```rust
|
||||
// let p = Pin { pointer: &mut <temporary> };
|
||||
// let p = Pin { __pointer: &mut <temporary> };
|
||||
// ```
|
||||
// becomes:
|
||||
// ```rust
|
||||
// let mut anon = <temporary>;
|
||||
// let p = Pin { pointer: &mut anon };
|
||||
// let p = Pin { __pointer: &mut anon };
|
||||
// ```
|
||||
// which is *exactly* what we want.
|
||||
//
|
||||
// See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
|
||||
// for more info.
|
||||
$crate::pin::Pin::<&mut _> { pointer: &mut { $value } }
|
||||
$crate::pin::Pin::<&mut _> { __pointer: &mut { $value } }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#![feature(alloc_layout_extra)]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(array_methods)]
|
||||
#![feature(array_windows)]
|
||||
#![feature(ascii_char)]
|
||||
#![feature(ascii_char_variants)]
|
||||
|
|
|
@ -95,7 +95,7 @@ static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
|
|||
#[inline]
|
||||
fn init_or_get_process_heap() -> c::HANDLE {
|
||||
let heap = HEAP.load(Ordering::Relaxed);
|
||||
if heap.is_null() {
|
||||
if core::intrinsics::unlikely(heap.is_null()) {
|
||||
// `HEAP` has not yet been successfully initialized
|
||||
let heap = unsafe { GetProcessHeap() };
|
||||
if !heap.is_null() {
|
||||
|
@ -115,6 +115,16 @@ fn init_or_get_process_heap() -> c::HANDLE {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
|
||||
let heap = init_or_get_process_heap();
|
||||
if core::intrinsics::unlikely(heap.is_null()) {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
|
||||
unsafe { HeapAlloc(heap, flags, dwBytes) }
|
||||
}
|
||||
|
||||
// Get a non-null handle to the default heap of the current process.
|
||||
// SAFETY: `HEAP` must have been successfully initialized.
|
||||
#[inline]
|
||||
|
@ -133,25 +143,17 @@ struct Header(*mut u8);
|
|||
// initialized.
|
||||
#[inline]
|
||||
unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
|
||||
let heap = init_or_get_process_heap();
|
||||
if heap.is_null() {
|
||||
// Allocation has failed, could not get the current process heap.
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
// Allocated memory will be either zeroed or uninitialized.
|
||||
let flags = if zeroed { HEAP_ZERO_MEMORY } else { 0 };
|
||||
|
||||
if layout.align() <= MIN_ALIGN {
|
||||
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
|
||||
// The returned pointer points to the start of an allocated block.
|
||||
unsafe { HeapAlloc(heap, flags, layout.size()) as *mut u8 }
|
||||
process_heap_alloc(flags, layout.size()) as *mut u8
|
||||
} else {
|
||||
// Allocate extra padding in order to be able to satisfy the alignment.
|
||||
let total = layout.align() + layout.size();
|
||||
|
||||
// SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
|
||||
let ptr = unsafe { HeapAlloc(heap, flags, total) as *mut u8 };
|
||||
let ptr = process_heap_alloc(flags, total) as *mut u8;
|
||||
if ptr.is_null() {
|
||||
// Allocation has failed.
|
||||
return ptr::null_mut();
|
||||
|
|
|
@ -99,9 +99,9 @@
|
|||
</Type>
|
||||
|
||||
<Type Name="core::pin::Pin<*>">
|
||||
<DisplayString>Pin({(void*)pointer}: {pointer})</DisplayString>
|
||||
<DisplayString>Pin({(void*)__pointer}: {__pointer})</DisplayString>
|
||||
<Expand>
|
||||
<ExpandedItem>pointer</ExpandedItem>
|
||||
<ExpandedItem>__pointer</ExpandedItem>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
html_playground_url = "https://play.rust-lang.org/"
|
||||
)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(array_methods)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
- _4 = g() -> [return: bb1, unwind unreachable];
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
|
||||
+ _3 = &mut _4;
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 };
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
|
||||
+ StorageDead(_3);
|
||||
+ StorageLive(_5);
|
||||
+ _5 = const false;
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
- _4 = g() -> [return: bb1, unwind continue];
|
||||
+ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
|
||||
+ _3 = &mut _4;
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 };
|
||||
+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
|
||||
+ StorageDead(_3);
|
||||
+ StorageLive(_5);
|
||||
+ _5 = const false;
|
||||
|
|
|
@ -7,7 +7,7 @@ use core::{marker::PhantomPinned, pin::Pin};
|
|||
|
||||
/// The `unsafe_pin_internals` is indeed unsound.
|
||||
fn non_unsafe_pin_new_unchecked<T>(pointer: &mut T) -> Pin<&mut T> {
|
||||
Pin { pointer }
|
||||
Pin { __pointer: pointer }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -34,15 +34,11 @@ error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIte
|
|||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
--> $DIR/issue-20605.rs:5:9
|
||||
error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
|
||||
--> $DIR/issue-20605.rs:5:17
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
--> $DIR/issue-20605.rs:5:5
|
||||
|
@ -54,11 +50,15 @@ LL | for item in *things { *item = 0 }
|
|||
note: required by a bound in `None`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
|
||||
--> $DIR/issue-20605.rs:5:17
|
||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
--> $DIR/issue-20605.rs:5:9
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
|
||||
--> $DIR/issue-20605.rs:5:27
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
fn foo() {
|
||||
let _ = 0..<10;
|
||||
//~^ ERROR: expected type, found `10`
|
||||
//~| HELP: remove the `<` to write an exclusive range
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
let _ = 0..<foo;
|
||||
//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
|
||||
//~| HELP: remove the `<` to write an exclusive range
|
||||
}
|
||||
|
||||
fn baz() {
|
||||
let _ = <foo>;
|
||||
//~^ ERROR: expected `::`, found `;`
|
||||
}
|
||||
|
||||
fn qux() {
|
||||
let _ = [1, 2, 3][..<1];
|
||||
//~^ ERROR: expected type, found `1`
|
||||
//~| HELP: remove the `<` to write an exclusive range
|
||||
}
|
||||
|
||||
fn quux() {
|
||||
let _ = [1, 2, 3][..<foo];
|
||||
//~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
|
||||
//~| HELP: remove the `<` to write an exclusive range
|
||||
}
|
||||
|
||||
fn foobar() {
|
||||
let _ = [1, 2, 3][..<foo>];
|
||||
//~^ ERROR: expected `::`, found `]`
|
||||
}
|
||||
|
||||
fn ok1() {
|
||||
let _ = [1, 2, 3][..<usize>::default()];
|
||||
}
|
||||
|
||||
fn ok2() {
|
||||
let _ = 0..<i32>::default();
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,46 @@
|
|||
error: expected type, found `10`
|
||||
--> $DIR/range-exclusive-dotdotlt.rs:2:17
|
||||
|
|
||||
LL | let _ = 0..<10;
|
||||
| -^^ expected type
|
||||
| |
|
||||
| help: remove the `<` to write an exclusive range
|
||||
|
||||
error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
|
||||
--> $DIR/range-exclusive-dotdotlt.rs:8:20
|
||||
|
|
||||
LL | let _ = 0..<foo;
|
||||
| - ^ expected one of 7 possible tokens
|
||||
| |
|
||||
| help: remove the `<` to write an exclusive range
|
||||
|
||||
error: expected `::`, found `;`
|
||||
--> $DIR/range-exclusive-dotdotlt.rs:14:18
|
||||
|
|
||||
LL | let _ = <foo>;
|
||||
| ^ expected `::`
|
||||
|
||||
error: expected type, found `1`
|
||||
--> $DIR/range-exclusive-dotdotlt.rs:19:26
|
||||
|
|
||||
LL | let _ = [1, 2, 3][..<1];
|
||||
| -^ expected type
|
||||
| |
|
||||
| help: remove the `<` to write an exclusive range
|
||||
|
||||
error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
|
||||
--> $DIR/range-exclusive-dotdotlt.rs:25:29
|
||||
|
|
||||
LL | let _ = [1, 2, 3][..<foo];
|
||||
| - ^ expected one of 7 possible tokens
|
||||
| |
|
||||
| help: remove the `<` to write an exclusive range
|
||||
|
||||
error: expected `::`, found `]`
|
||||
--> $DIR/range-exclusive-dotdotlt.rs:31:30
|
||||
|
|
||||
LL | let _ = [1, 2, 3][..<foo>];
|
||||
| ^ expected `::`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
fn main() {
|
||||
let f = |3: isize| println!("hello");
|
||||
//~^ ERROR refutable pattern in function argument
|
||||
//~^ ERROR refutable pattern in closure argument
|
||||
//~| `..=2_isize` and `4_isize..` not covered
|
||||
f(4);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in function argument
|
||||
error[E0005]: refutable pattern in closure argument
|
||||
--> $DIR/refutable-pattern-in-fn-arg.rs:2:14
|
||||
|
|
||||
LL | let f = |3: isize| println!("hello");
|
||||
|
|
|
@ -8,5 +8,5 @@ use core::{
|
|||
|
||||
fn main() {
|
||||
let mut phantom_pinned = pin!(PhantomPinned);
|
||||
mem::take(phantom_pinned.pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals'
|
||||
mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals'
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0658]: use of unstable library feature 'unsafe_pin_internals'
|
||||
--> $DIR/cant_access_internals.rs:11:15
|
||||
|
|
||||
LL | mem::take(phantom_pinned.pointer);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | mem::take(phantom_pinned.__pointer);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
|
|
@ -44,6 +44,7 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
|
|||
| type must be known at this point
|
||||
|
|
||||
= note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate:
|
||||
- impl From<Char> for u32;
|
||||
- impl From<Ipv4Addr> for u32;
|
||||
- impl From<NonZeroU32> for u32;
|
||||
- impl From<bool> for u32;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
// Similar to tests/ui/traits/next-solver/tait-eq-proj.rs
|
||||
// Similar to tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
|
||||
// but check the alias-sub relation in the other direction.
|
||||
|
||||
type Tait = impl Iterator<Item = impl Sized>;
|
|
@ -0,0 +1,18 @@
|
|||
// compile-flags: -Znext-solver
|
||||
// check-pass
|
||||
|
||||
trait Mirror {
|
||||
type Assoc;
|
||||
}
|
||||
impl<T> Mirror for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn new() -> Self { Foo }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<Foo as Mirror>::Assoc::new();
|
||||
}
|
|
@ -16,6 +16,7 @@ fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc
|
|||
//~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:17
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:17
|
||||
|
|
||||
|
@ -35,7 +43,8 @@ LL | needs_bar::<T::Assoc1>();
|
|||
| ^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
@ -12,6 +12,7 @@ fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
|
|||
//~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
//~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
|
||||
--> $DIR/recursive-self-normalization.rs:11:17
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
--> $DIR/recursive-self-normalization.rs:11:17
|
||||
|
|
||||
|
@ -35,7 +43,8 @@ LL | needs_bar::<T::Assoc>();
|
|||
| ^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
// compile-flags: -Znext-solver
|
||||
// check-pass
|
||||
|
||||
// Checks that we don't explode when we assemble >1 candidate for a goal.
|
||||
|
||||
struct Wrapper<T>(T);
|
||||
|
||||
trait Foo {}
|
||||
|
||||
impl Foo for Wrapper<i32> {}
|
||||
|
||||
impl Foo for Wrapper<()> {}
|
||||
|
||||
fn needs_foo(_: impl Foo) {}
|
||||
|
||||
fn main() {
|
||||
let mut x = Default::default();
|
||||
let w = Wrapper(x);
|
||||
needs_foo(w);
|
||||
x = 1;
|
||||
let _ = x;
|
||||
}
|
|
@ -12,6 +12,7 @@ LL | Ok(Err(123_i32)?)
|
|||
= help: the following other types implement trait `From<T>`:
|
||||
<u8 as From<bool>>
|
||||
<u8 as From<NonZeroU8>>
|
||||
<u8 as From<Char>>
|
||||
= note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// compile-flags: -Zvalidate-mir
|
||||
// check-pass
|
||||
|
||||
// Check that we don't cause cycle errors when validating pre-`Reveal::All` MIR
|
||||
// that assigns opaques through normalized projections.
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
struct Bar;
|
||||
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
fn foo() -> Foo;
|
||||
}
|
||||
|
||||
impl Trait for Bar {
|
||||
type Assoc = impl std::fmt::Debug;
|
||||
fn foo() -> Foo
|
||||
where
|
||||
Self::Assoc:,
|
||||
{
|
||||
let x: <Bar as Trait>::Assoc = ();
|
||||
Foo { field: () }
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
field: <Bar as Trait>::Assoc,
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -652,6 +652,7 @@ compiler-team-contributors = [
|
|||
"@TaKO8Ki",
|
||||
"@b-naber",
|
||||
"@nnethercote",
|
||||
"@fmease",
|
||||
]
|
||||
compiler = [
|
||||
"compiler-team",
|
||||
|
|
Loading…
Reference in New Issue