Auto merge of #141366 - matthiaskrgr:rollup-utvtyy3, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #140526 (docs: Specify that common sort functions sort in an ascending direction) - #141230 (std: fix doctest and explain for `as_slices` and `as_mut_slices` in `VecDeque`) - #141341 (limit impls of `VaArgSafe` to just types that are actually safe) - #141347 (incorrectly prefer builtin `dyn` impls :3) - #141351 (Move -Zcrate-attr injection to just after crate root parsing) - #141356 (lower bodies' params to thir before the body's value) - #141357 (`unpretty=thir-tree`: don't require the final expr to be the body's value) - #141363 (Document why we allow escaping bound vars in LTA norm) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5df0f729f5
15 changed files with 207 additions and 85 deletions
|
|
@ -45,7 +45,7 @@ use crate::interface::Compiler;
|
|||
use crate::{errors, limits, proc_macro_decls, util};
|
||||
|
||||
pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
|
||||
let krate = sess
|
||||
let mut krate = sess
|
||||
.time("parse_crate", || {
|
||||
let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
|
||||
Input::File(file) => new_parser_from_file(&sess.psess, file, None),
|
||||
|
|
@ -64,6 +64,12 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
|
|||
input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
|
||||
}
|
||||
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
&mut krate,
|
||||
&sess.psess,
|
||||
&sess.opts.unstable_opts.crate_attr,
|
||||
);
|
||||
|
||||
krate
|
||||
}
|
||||
|
||||
|
|
@ -805,17 +811,11 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
|
|||
|
||||
pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
|
||||
compiler: &Compiler,
|
||||
mut krate: rustc_ast::Crate,
|
||||
krate: rustc_ast::Crate,
|
||||
f: F,
|
||||
) -> T {
|
||||
let sess = &compiler.sess;
|
||||
|
||||
rustc_builtin_macros::cmdline_attrs::inject(
|
||||
&mut krate,
|
||||
&sess.psess,
|
||||
&sess.opts.unstable_opts.crate_attr,
|
||||
);
|
||||
|
||||
let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
|
||||
|
||||
let crate_name = get_crate_name(sess, &pre_configured_attrs);
|
||||
|
|
|
|||
|
|
@ -450,10 +450,6 @@ fn construct_fn<'tcx>(
|
|||
let span = tcx.def_span(fn_def);
|
||||
let fn_id = tcx.local_def_id_to_hir_id(fn_def);
|
||||
|
||||
// The representation of thir for `-Zunpretty=thir-tree` relies on
|
||||
// the entry expression being the last element of `thir.exprs`.
|
||||
assert_eq!(expr.as_usize(), thir.exprs.len() - 1);
|
||||
|
||||
// Figure out what primary body this item has.
|
||||
let body = tcx.hir_body_owned_by(fn_def);
|
||||
let span_with_body = tcx.hir_span_with_body(fn_id);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ pub(crate) fn thir_body(
|
|||
if let Some(reported) = cx.typeck_results.tainted_by_errors {
|
||||
return Err(reported);
|
||||
}
|
||||
let expr = cx.mirror_expr(body.value);
|
||||
|
||||
// Lower the params before the body's expression so errors from params are shown first.
|
||||
let owner_id = tcx.local_def_id_to_hir_id(owner_def);
|
||||
if let Some(fn_decl) = tcx.hir_fn_decl_by_hir_id(owner_id) {
|
||||
let closure_env_param = cx.closure_env_param(owner_def, owner_id);
|
||||
|
|
@ -48,6 +48,7 @@ pub(crate) fn thir_body(
|
|||
}
|
||||
}
|
||||
|
||||
let expr = cx.mirror_expr(body.value);
|
||||
Ok((tcx.alloc_steal_thir(cx.thir), expr))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ use rustc_span::def_id::LocalDefId;
|
|||
/// Create a THIR tree for debugging.
|
||||
pub fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
|
||||
match super::cx::thir_body(tcx, owner_def) {
|
||||
Ok((thir, _)) => {
|
||||
Ok((thir, expr)) => {
|
||||
let thir = thir.steal();
|
||||
let mut printer = ThirPrinter::new(&thir);
|
||||
printer.print();
|
||||
printer.print(expr);
|
||||
printer.into_buffer()
|
||||
}
|
||||
Err(_) => "error".into(),
|
||||
|
|
@ -58,7 +58,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn print(&mut self) {
|
||||
fn print(&mut self, body_expr: ExprId) {
|
||||
print_indented!(self, "params: [", 0);
|
||||
for param in self.thir.params.iter() {
|
||||
self.print_param(param, 1);
|
||||
|
|
@ -66,8 +66,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
print_indented!(self, "]", 0);
|
||||
|
||||
print_indented!(self, "body:", 0);
|
||||
let expr = ExprId::from_usize(self.thir.exprs.len() - 1);
|
||||
self.print_expr(expr, 1);
|
||||
self.print_expr(body_expr, 1);
|
||||
}
|
||||
|
||||
fn into_buffer(self) -> String {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_type_ir::{
|
|||
self as ty, Interner, Movability, TraitPredicate, TypeVisitableExt as _, TypingMode,
|
||||
Upcast as _, elaborate,
|
||||
};
|
||||
use tracing::{instrument, trace};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
use crate::solve::assembly::structural_traits::{self, AsyncCallableRelevantTypes};
|
||||
|
|
@ -17,7 +17,7 @@ use crate::solve::assembly::{self, AllowInferenceConstraints, AssembleCandidates
|
|||
use crate::solve::inspect::ProbeKind;
|
||||
use crate::solve::{
|
||||
BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, MaybeCause,
|
||||
NoSolution, ParamEnvSource, QueryResult,
|
||||
NoSolution, ParamEnvSource, QueryResult, has_only_region_constraints,
|
||||
};
|
||||
|
||||
impl<D, I> assembly::GoalKind<D> for TraitPredicate<I>
|
||||
|
|
@ -1253,6 +1253,45 @@ where
|
|||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
/// FIXME(#57893): For backwards compatability with the old trait solver implementation,
|
||||
/// we need to handle overlap between builtin and user-written impls for trait objects.
|
||||
///
|
||||
/// This overlap is unsound in general and something which we intend to fix separately.
|
||||
/// To avoid blocking the stabilization of the trait solver, we add this hack to avoid
|
||||
/// breakage in cases which are *mostly fine*™. Importantly, this preference is strictly
|
||||
/// weaker than the old behavior.
|
||||
///
|
||||
/// We only prefer builtin over user-written impls if there are no inference constraints.
|
||||
/// Importantly, we also only prefer the builtin impls for trait goals, and not during
|
||||
/// normalization. This means the only case where this special-case results in exploitable
|
||||
/// unsoundness should be lifetime dependent user-written impls.
|
||||
pub(super) fn unsound_prefer_builtin_dyn_impl(&mut self, candidates: &mut Vec<Candidate<I>>) {
|
||||
match self.typing_mode() {
|
||||
TypingMode::Coherence => return,
|
||||
TypingMode::Analysis { .. }
|
||||
| TypingMode::Borrowck { .. }
|
||||
| TypingMode::PostBorrowckAnalysis { .. }
|
||||
| TypingMode::PostAnalysis => {}
|
||||
}
|
||||
|
||||
if candidates
|
||||
.iter()
|
||||
.find(|c| {
|
||||
matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_)))
|
||||
})
|
||||
.is_some_and(|c| has_only_region_constraints(c.result))
|
||||
{
|
||||
candidates.retain(|c| {
|
||||
if matches!(c.source, CandidateSource::Impl(_)) {
|
||||
debug!(?c, "unsoundly dropping impl in favor of builtin dyn-candidate");
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub(super) fn merge_trait_candidates(
|
||||
&mut self,
|
||||
|
|
@ -1313,6 +1352,7 @@ where
|
|||
}
|
||||
|
||||
self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates);
|
||||
self.unsound_prefer_builtin_dyn_impl(&mut candidates);
|
||||
|
||||
// If there are *only* global where bounds, then make sure to return that this
|
||||
// is still reported as being proven-via the param-env so that rigid projections
|
||||
|
|
|
|||
|
|
@ -299,12 +299,21 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
// We don't replace bound vars in the generic arguments of the free alias with
|
||||
// placeholders. This doesn't cause any issues as instantiating parameters with
|
||||
// bound variables is special-cased to rewrite the debruijn index to be higher
|
||||
// whenever we fold through a binder.
|
||||
//
|
||||
// However, we do replace any escaping bound vars in the resulting goals with
|
||||
// placeholders as the trait solver does not expect to encounter escaping bound
|
||||
// vars in obligations.
|
||||
//
|
||||
// FIXME(lazy_type_alias): Check how much this actually matters for perf before
|
||||
// stabilization. This is a bit weird and generally not how we handle binders in
|
||||
// the compiler so ideally we'd do the same boundvar->placeholder->boundvar dance
|
||||
// that other kinds of normalization do.
|
||||
let infcx = self.selcx.infcx;
|
||||
self.obligations.extend(
|
||||
// FIXME(BoxyUwU):
|
||||
// FIXME(lazy_type_alias):
|
||||
// It seems suspicious to instantiate the predicates with arguments that might be bound vars,
|
||||
// we might wind up instantiating one of these bound vars underneath a hrtb.
|
||||
infcx.tcx.predicates_of(free.def_id).instantiate_own(infcx.tcx, free.args).map(
|
||||
|(mut predicate, span)| {
|
||||
if free.has_escaping_bound_vars() {
|
||||
|
|
|
|||
|
|
@ -1312,6 +1312,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
///
|
||||
/// If [`make_contiguous`] was previously called, all elements of the
|
||||
/// deque will be in the first slice and the second slice will be empty.
|
||||
/// Otherwise, the exact split point depends on implementation details
|
||||
/// and is not guaranteed.
|
||||
///
|
||||
/// [`make_contiguous`]: VecDeque::make_contiguous
|
||||
///
|
||||
|
|
@ -1326,12 +1328,18 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// deque.push_back(1);
|
||||
/// deque.push_back(2);
|
||||
///
|
||||
/// assert_eq!(deque.as_slices(), (&[0, 1, 2][..], &[][..]));
|
||||
/// let expected = [0, 1, 2];
|
||||
/// let (front, back) = deque.as_slices();
|
||||
/// assert_eq!(&expected[..front.len()], front);
|
||||
/// assert_eq!(&expected[front.len()..], back);
|
||||
///
|
||||
/// deque.push_front(10);
|
||||
/// deque.push_front(9);
|
||||
///
|
||||
/// assert_eq!(deque.as_slices(), (&[9, 10][..], &[0, 1, 2][..]));
|
||||
/// let expected = [9, 10, 0, 1, 2];
|
||||
/// let (front, back) = deque.as_slices();
|
||||
/// assert_eq!(&expected[..front.len()], front);
|
||||
/// assert_eq!(&expected[front.len()..], back);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
|
|
@ -1347,6 +1355,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
///
|
||||
/// If [`make_contiguous`] was previously called, all elements of the
|
||||
/// deque will be in the first slice and the second slice will be empty.
|
||||
/// Otherwise, the exact split point depends on implementation details
|
||||
/// and is not guaranteed.
|
||||
///
|
||||
/// [`make_contiguous`]: VecDeque::make_contiguous
|
||||
///
|
||||
|
|
@ -1363,9 +1373,22 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// deque.push_front(10);
|
||||
/// deque.push_front(9);
|
||||
///
|
||||
/// deque.as_mut_slices().0[0] = 42;
|
||||
/// deque.as_mut_slices().1[0] = 24;
|
||||
/// assert_eq!(deque.as_slices(), (&[42, 10][..], &[24, 1][..]));
|
||||
/// // Since the split point is not guaranteed, we may need to update
|
||||
/// // either slice.
|
||||
/// let mut update_nth = |index: usize, val: u32| {
|
||||
/// let (front, back) = deque.as_mut_slices();
|
||||
/// if index > front.len() - 1 {
|
||||
/// back[index - front.len()] = val;
|
||||
/// } else {
|
||||
/// front[index] = val;
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
/// update_nth(0, 42);
|
||||
/// update_nth(2, 24);
|
||||
///
|
||||
/// let v: Vec<_> = deque.into();
|
||||
/// assert_eq!(v, [42, 10, 24, 1]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ use crate::boxed::Box;
|
|||
use crate::vec::Vec;
|
||||
|
||||
impl<T> [T] {
|
||||
/// Sorts the slice, preserving initial order of equal elements.
|
||||
/// Sorts the slice in ascending order, preserving initial order of equal elements.
|
||||
///
|
||||
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
|
||||
/// worst-case.
|
||||
|
|
@ -137,7 +137,8 @@ impl<T> [T] {
|
|||
stable_sort(self, T::lt);
|
||||
}
|
||||
|
||||
/// Sorts the slice with a comparison function, preserving initial order of equal elements.
|
||||
/// Sorts the slice in ascending order with a comparison function, preserving initial order of
|
||||
/// equal elements.
|
||||
///
|
||||
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
|
||||
/// worst-case.
|
||||
|
|
@ -197,7 +198,8 @@ impl<T> [T] {
|
|||
stable_sort(self, |a, b| compare(a, b) == Less);
|
||||
}
|
||||
|
||||
/// Sorts the slice with a key extraction function, preserving initial order of equal elements.
|
||||
/// Sorts the slice in ascending order with a key extraction function, preserving initial order
|
||||
/// of equal elements.
|
||||
///
|
||||
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
|
||||
/// worst-case, where the key function is *O*(*m*).
|
||||
|
|
@ -252,7 +254,8 @@ impl<T> [T] {
|
|||
stable_sort(self, |a, b| f(a).lt(&f(b)));
|
||||
}
|
||||
|
||||
/// Sorts the slice with a key extraction function, preserving initial order of equal elements.
|
||||
/// Sorts the slice in ascending order with a key extraction function, preserving initial order
|
||||
/// of equal elements.
|
||||
///
|
||||
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* + *n* \*
|
||||
/// log(*n*)) worst-case, where the key function is *O*(*m*).
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub mod c_str;
|
|||
issue = "44930",
|
||||
reason = "the `c_variadic` feature has not been properly tested on all supported platforms"
|
||||
)]
|
||||
pub use self::va_list::{VaList, VaListImpl};
|
||||
pub use self::va_list::{VaArgSafe, VaList, VaListImpl};
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
|
|
|
|||
|
|
@ -223,39 +223,57 @@ impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
|
|||
}
|
||||
}
|
||||
|
||||
// The VaArgSafe trait needs to be used in public interfaces, however, the trait
|
||||
// itself must not be allowed to be used outside this module. Allowing users to
|
||||
// implement the trait for a new type (thereby allowing the va_arg intrinsic to
|
||||
// be used on a new type) is likely to cause undefined behavior.
|
||||
//
|
||||
// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
|
||||
// but also ensure it cannot be used elsewhere, the trait needs to be public
|
||||
// within a private module. Once RFC 2145 has been implemented look into
|
||||
// improving this.
|
||||
mod sealed_trait {
|
||||
/// Trait which permits the allowed types to be used with [super::VaListImpl::arg].
|
||||
pub unsafe trait VaArgSafe {}
|
||||
mod sealed {
|
||||
pub trait Sealed {}
|
||||
|
||||
impl Sealed for i32 {}
|
||||
impl Sealed for i64 {}
|
||||
impl Sealed for isize {}
|
||||
|
||||
impl Sealed for u32 {}
|
||||
impl Sealed for u64 {}
|
||||
impl Sealed for usize {}
|
||||
|
||||
impl Sealed for f64 {}
|
||||
|
||||
impl<T> Sealed for *mut T {}
|
||||
impl<T> Sealed for *const T {}
|
||||
}
|
||||
|
||||
macro_rules! impl_va_arg_safe {
|
||||
($($t:ty),+) => {
|
||||
$(
|
||||
unsafe impl sealed_trait::VaArgSafe for $t {}
|
||||
)+
|
||||
}
|
||||
}
|
||||
/// Trait which permits the allowed types to be used with [`VaListImpl::arg`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait must only be implemented for types that C passes as varargs without implicit promotion.
|
||||
///
|
||||
/// In C varargs, integers smaller than [`c_int`] and floats smaller than [`c_double`]
|
||||
/// are implicitly promoted to [`c_int`] and [`c_double`] respectively. Implementing this trait for
|
||||
/// types that are subject to this promotion rule is invalid.
|
||||
///
|
||||
/// [`c_int`]: core::ffi::c_int
|
||||
/// [`c_double`]: core::ffi::c_double
|
||||
pub unsafe trait VaArgSafe: sealed::Sealed {}
|
||||
|
||||
impl_va_arg_safe! {i8, i16, i32, i64, usize}
|
||||
impl_va_arg_safe! {u8, u16, u32, u64, isize}
|
||||
impl_va_arg_safe! {f64}
|
||||
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
|
||||
unsafe impl VaArgSafe for i32 {}
|
||||
unsafe impl VaArgSafe for i64 {}
|
||||
unsafe impl VaArgSafe for isize {}
|
||||
|
||||
unsafe impl<T> sealed_trait::VaArgSafe for *mut T {}
|
||||
unsafe impl<T> sealed_trait::VaArgSafe for *const T {}
|
||||
// u8 and u16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
|
||||
unsafe impl VaArgSafe for u32 {}
|
||||
unsafe impl VaArgSafe for u64 {}
|
||||
unsafe impl VaArgSafe for usize {}
|
||||
|
||||
// f32 is implicitly promoted to c_double in C, and cannot implement `VaArgSafe`.
|
||||
unsafe impl VaArgSafe for f64 {}
|
||||
|
||||
unsafe impl<T> VaArgSafe for *mut T {}
|
||||
unsafe impl<T> VaArgSafe for *const T {}
|
||||
|
||||
impl<'f> VaListImpl<'f> {
|
||||
/// Advance to the next arg.
|
||||
#[inline]
|
||||
pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
|
||||
pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
|
||||
// SAFETY: the caller must uphold the safety contract for `va_arg`.
|
||||
unsafe { va_arg(self) }
|
||||
}
|
||||
|
|
@ -317,4 +335,4 @@ unsafe fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
|
|||
/// argument `ap` points to.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
unsafe fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
|
||||
unsafe fn va_arg<T: VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
|
||||
|
|
|
|||
|
|
@ -2986,7 +2986,7 @@ impl<T> [T] {
|
|||
self.binary_search_by(|k| f(k).cmp(b))
|
||||
}
|
||||
|
||||
/// Sorts the slice **without** preserving the initial order of equal elements.
|
||||
/// Sorts the slice in ascending order **without** preserving the initial order of equal elements.
|
||||
///
|
||||
/// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not
|
||||
/// allocate), and *O*(*n* \* log(*n*)) worst-case.
|
||||
|
|
@ -3047,8 +3047,8 @@ impl<T> [T] {
|
|||
sort::unstable::sort(self, &mut T::lt);
|
||||
}
|
||||
|
||||
/// Sorts the slice with a comparison function, **without** preserving the initial order of
|
||||
/// equal elements.
|
||||
/// Sorts the slice in ascending order with a comparison function, **without** preserving the
|
||||
/// initial order of equal elements.
|
||||
///
|
||||
/// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not
|
||||
/// allocate), and *O*(*n* \* log(*n*)) worst-case.
|
||||
|
|
@ -3102,8 +3102,8 @@ impl<T> [T] {
|
|||
sort::unstable::sort(self, &mut |a, b| compare(a, b) == Ordering::Less);
|
||||
}
|
||||
|
||||
/// Sorts the slice with a key extraction function, **without** preserving the initial order of
|
||||
/// equal elements.
|
||||
/// Sorts the slice in ascending order with a key extraction function, **without** preserving
|
||||
/// the initial order of equal elements.
|
||||
///
|
||||
/// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not
|
||||
/// allocate), and *O*(*n* \* log(*n*)) worst-case.
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ pub use core::ffi::c_void;
|
|||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
pub use core::ffi::{VaList, VaListImpl};
|
||||
pub use core::ffi::{VaArgSafe, VaList, VaListImpl};
|
||||
#[stable(feature = "core_ffi_c", since = "1.64.0")]
|
||||
pub use core::ffi::{
|
||||
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ pub unsafe extern "C" fn check_list_0(mut ap: VaList) -> usize {
|
|||
#[no_mangle]
|
||||
pub unsafe extern "C" fn check_list_1(mut ap: VaList) -> usize {
|
||||
continue_if!(ap.arg::<c_int>() == -1);
|
||||
continue_if!(ap.arg::<c_char>() == 'A' as c_char);
|
||||
continue_if!(ap.arg::<c_char>() == '4' as c_char);
|
||||
continue_if!(ap.arg::<c_char>() == ';' as c_char);
|
||||
continue_if!(ap.arg::<c_int>() == 'A' as c_int);
|
||||
continue_if!(ap.arg::<c_int>() == '4' as c_int);
|
||||
continue_if!(ap.arg::<c_int>() == ';' as c_int);
|
||||
continue_if!(ap.arg::<c_int>() == 0x32);
|
||||
continue_if!(ap.arg::<c_int>() == 0x10000001);
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Valid!"));
|
||||
|
|
@ -43,7 +43,7 @@ pub unsafe extern "C" fn check_list_1(mut ap: VaList) -> usize {
|
|||
pub unsafe extern "C" fn check_list_2(mut ap: VaList) -> usize {
|
||||
continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
|
||||
continue_if!(ap.arg::<c_long>() == 12);
|
||||
continue_if!(ap.arg::<c_char>() == 'a' as c_char);
|
||||
continue_if!(ap.arg::<c_int>() == 'a' as c_int);
|
||||
continue_if!(ap.arg::<c_double>().floor() == 6.18f64.floor());
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello"));
|
||||
continue_if!(ap.arg::<c_int>() == 42);
|
||||
|
|
@ -55,7 +55,7 @@ pub unsafe extern "C" fn check_list_2(mut ap: VaList) -> usize {
|
|||
pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize {
|
||||
continue_if!(ap.arg::<c_double>().floor() == 6.28f64.floor());
|
||||
continue_if!(ap.arg::<c_int>() == 16);
|
||||
continue_if!(ap.arg::<c_char>() == 'A' as c_char);
|
||||
continue_if!(ap.arg::<c_int>() == 'A' as c_int);
|
||||
continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Skip Me!"));
|
||||
ap.with_copy(
|
||||
|mut ap| {
|
||||
|
|
@ -75,7 +75,7 @@ pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize {
|
|||
pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize {
|
||||
continue_if!(ap.arg::<c_double>().floor() == 3.14f64.floor());
|
||||
continue_if!(ap.arg::<c_long>() == 12);
|
||||
continue_if!(ap.arg::<c_char>() == 'A' as c_char);
|
||||
continue_if!(ap.arg::<c_int>() == 'A' as c_int);
|
||||
continue_if!(ap.arg::<c_longlong>() == 1);
|
||||
0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,19 @@ LL | pub fn test<A: Foo, B: Foo>(arg: EFoo) {
|
|||
LL | B::X => println!("B::X"),
|
||||
| ^^^^ `const` depends on a generic parameter
|
||||
|
||||
error[E0158]: constant pattern cannot depend on generic parameters
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:28:48
|
||||
|
|
||||
LL | pub trait Foo {
|
||||
| -------------
|
||||
LL | const X: EFoo;
|
||||
| ------------- constant defined here
|
||||
...
|
||||
LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
|
||||
| - ^^^^ `const` depends on a generic parameter
|
||||
| |
|
||||
| constant depends on this generic parameter
|
||||
|
||||
error[E0158]: constant pattern cannot depend on generic parameters
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:30:9
|
||||
|
|
||||
|
|
@ -40,19 +53,6 @@ LL |
|
|||
LL | let A::X = arg;
|
||||
| ^^^^ `const` depends on a generic parameter
|
||||
|
||||
error[E0158]: constant pattern cannot depend on generic parameters
|
||||
--> $DIR/associated-const-type-parameter-pattern.rs:28:48
|
||||
|
|
||||
LL | pub trait Foo {
|
||||
| -------------
|
||||
LL | const X: EFoo;
|
||||
| ------------- constant defined here
|
||||
...
|
||||
LL | pub fn test_let_pat<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
|
||||
| - ^^^^ `const` depends on a generic parameter
|
||||
| |
|
||||
| constant depends on this generic parameter
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
|
||||
// A regression test for trait-system-refactor-initiative#183. While
|
||||
// this concrete instance is likely not practically unsound, the general
|
||||
// pattern is, see #57893.
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
unsafe trait TidAble<'a>: Tid<'a> {}
|
||||
trait TidExt<'a>: Tid<'a> {
|
||||
fn downcast_box(self: Box<Self>) {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, X: ?Sized + Tid<'a>> TidExt<'a> for X {}
|
||||
|
||||
unsafe trait Tid<'a>: 'a {}
|
||||
|
||||
unsafe impl<'a, T: ?Sized + TidAble<'a>> Tid<'a> for T {}
|
||||
|
||||
impl<'a> dyn Tid<'a> + 'a {
|
||||
fn downcast_any_box(self: Box<Self>) {
|
||||
self.downcast_box();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> TidAble<'a> for dyn Tid<'a> + 'a {}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue