mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-16 05:56:56 +00:00
Auto merge of #129024 - matthiaskrgr:rollup-uj1pd0x, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #128712 (Normalize struct tail properly for `dyn` ptr-to-ptr casting in new solver) - #128912 (Store `do_not_recommend`-ness in impl header) - #129000 (bootstrap: clear miri ui-test deps when miri sysroot gets rebuilt) - #129013 (Remove unused script from run-make tests) - #129017 (Replace `std::fmt:FormatterFn` with `std::fmt::from_fn`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
db5704ffca
@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
|
||||
use rustc_trait_selection::traits::ObligationCause;
|
||||
|
||||
@ -165,6 +166,52 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
result.unwrap_or(value)
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn struct_tail(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
location: impl NormalizeLocation,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
if self.infcx.next_trait_solver() {
|
||||
let body = self.body;
|
||||
let param_env = self.param_env;
|
||||
self.fully_perform_op(
|
||||
location.to_locations(),
|
||||
ConstraintCategory::Boring,
|
||||
CustomTypeOp::new(
|
||||
|ocx| {
|
||||
let structurally_normalize = |ty| {
|
||||
ocx.structurally_normalize(
|
||||
&ObligationCause::misc(
|
||||
location.to_locations().span(body),
|
||||
body.source.def_id().expect_local(),
|
||||
),
|
||||
param_env,
|
||||
ty,
|
||||
)
|
||||
.unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR"))
|
||||
};
|
||||
|
||||
let tail = tcx.struct_tail_raw(
|
||||
ty,
|
||||
structurally_normalize,
|
||||
|| {},
|
||||
);
|
||||
|
||||
Ok(tail)
|
||||
},
|
||||
"normalizing struct tail",
|
||||
),
|
||||
)
|
||||
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
|
||||
} else {
|
||||
let mut normalize = |ty| self.normalize(ty, location);
|
||||
let tail = tcx.struct_tail_raw(ty, &mut normalize, || {});
|
||||
normalize(tail)
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
pub(super) fn ascribe_user_type(
|
||||
&mut self,
|
||||
|
@ -2329,17 +2329,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
let cast_ty_to = CastTy::from_ty(*ty);
|
||||
match (cast_ty_from, cast_ty_to) {
|
||||
(Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
|
||||
let mut normalize = |t| self.normalize(t, location);
|
||||
|
||||
// N.B. `struct_tail_with_normalize` only "structurally resolves"
|
||||
// the type. It is not fully normalized, so we have to normalize it
|
||||
// afterwards.
|
||||
let src_tail =
|
||||
tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ());
|
||||
let src_tail = normalize(src_tail);
|
||||
let dst_tail =
|
||||
tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ());
|
||||
let dst_tail = normalize(dst_tail);
|
||||
let src_tail = self.struct_tail(src.ty, location);
|
||||
let dst_tail = self.struct_tail(dst.ty, location);
|
||||
|
||||
// This checks (lifetime part of) vtable validity for pointer casts,
|
||||
// which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
|
||||
|
@ -226,7 +226,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
|
||||
debug_assert!(
|
||||
matches!(
|
||||
ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(),
|
||||
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(),
|
||||
ty::Str | ty::Slice(..),
|
||||
),
|
||||
"`ConstValue::Slice` is for slice-tailed types only, but got {}",
|
||||
|
@ -195,7 +195,7 @@ fn reconstruct_place_meta<'tcx>(
|
||||
|
||||
let mut last_valtree = valtree;
|
||||
// Traverse the type, and update `last_valtree` as we go.
|
||||
let tail = tcx.struct_tail_with_normalize(
|
||||
let tail = tcx.struct_tail_raw(
|
||||
layout.ty,
|
||||
|ty| ty,
|
||||
|| {
|
||||
|
@ -1700,6 +1700,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
||||
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||
safety: impl_.safety,
|
||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
||||
do_not_recommend: tcx.features().do_not_recommend
|
||||
&& tcx.has_attrs_with_path(def_id, &[sym::diagnostic, sym::do_not_recommend]),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return Ok(Some(PointerKind::Thin));
|
||||
}
|
||||
|
||||
let t = self.try_structurally_resolve_type(span, t);
|
||||
|
||||
Ok(match *t.kind() {
|
||||
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
|
||||
ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty)),
|
||||
|
@ -70,7 +70,8 @@ impl<'a, 'tcx> Expectation<'tcx> {
|
||||
/// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
|
||||
/// for examples of where this comes up,.
|
||||
pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
|
||||
match fcx.tcx.struct_tail_without_normalization(ty).kind() {
|
||||
// FIXME: This is not right, even in the old solver...
|
||||
match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}).kind() {
|
||||
ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty),
|
||||
_ => ExpectHasType(ty),
|
||||
}
|
||||
|
@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
code: traits::ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
if !ty.references_error() {
|
||||
let tail = self.tcx.struct_tail_with_normalize(
|
||||
let tail = self.tcx.struct_tail_raw(
|
||||
ty,
|
||||
|ty| {
|
||||
if self.next_trait_solver() {
|
||||
|
@ -3176,6 +3176,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
|
||||
self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity)
|
||||
}
|
||||
|
||||
/// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
|
||||
pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
|
||||
matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true })
|
||||
&& self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameter attributes that can only be determined by examining the body of a function instead
|
||||
|
@ -362,7 +362,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
|
||||
let tail = tcx.struct_tail_with_normalize(
|
||||
let tail = tcx.struct_tail_raw(
|
||||
pointee,
|
||||
|ty| match tcx.try_normalize_erasing_regions(param_env, ty) {
|
||||
Ok(ty) => ty,
|
||||
|
@ -262,6 +262,7 @@ pub struct ImplTraitHeader<'tcx> {
|
||||
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
|
||||
pub polarity: ImplPolarity,
|
||||
pub safety: hir::Safety,
|
||||
pub do_not_recommend: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
|
||||
|
@ -1590,7 +1590,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
|
||||
) -> Result<Ty<'tcx>, Ty<'tcx>> {
|
||||
let tail = tcx.struct_tail_with_normalize(self, normalize, || {});
|
||||
let tail = tcx.struct_tail_raw(self, normalize, || {});
|
||||
match tail.kind() {
|
||||
// Sized types
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
@ -1614,10 +1614,10 @@ impl<'tcx> Ty<'tcx> {
|
||||
| ty::Foreign(..)
|
||||
// `dyn*` has metadata = ().
|
||||
| ty::Dynamic(_, _, ty::DynStar)
|
||||
// If returned by `struct_tail_with_normalize` this is a unit struct
|
||||
// If returned by `struct_tail_raw` this is a unit struct
|
||||
// without any fields, or not a struct, and therefore is Sized.
|
||||
| ty::Adt(..)
|
||||
// If returned by `struct_tail_with_normalize` this is the empty tuple,
|
||||
// If returned by `struct_tail_raw` this is the empty tuple,
|
||||
// a.k.a. unit type, which is Sized
|
||||
| ty::Tuple(..) => Ok(tcx.types.unit),
|
||||
|
||||
|
@ -171,14 +171,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to returns the deeply last field of nested structures, but
|
||||
/// does not apply any normalization in its search. Returns the same type
|
||||
/// if input `ty` is not a structure at all.
|
||||
pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let tcx = self;
|
||||
tcx.struct_tail_with_normalize(ty, |ty| ty, || {})
|
||||
}
|
||||
|
||||
/// Returns the deeply last field of nested structures, or the same type if
|
||||
/// not a structure at all. Corresponds to the only possible unsized field,
|
||||
/// and its type can be used to determine unsizing strategy.
|
||||
@ -188,7 +180,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// normalization attempt may cause compiler bugs.
|
||||
pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||
let tcx = self;
|
||||
tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
|
||||
tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
|
||||
}
|
||||
|
||||
/// Returns the deeply last field of nested structures, or the same type if
|
||||
@ -196,12 +188,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// and its type can be used to determine unsizing strategy.
|
||||
///
|
||||
/// This is parameterized over the normalization strategy (i.e. how to
|
||||
/// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
|
||||
/// function to indicate no normalization should take place.
|
||||
/// handle `<T as Trait>::Assoc` and `impl Trait`). You almost certainly do
|
||||
/// **NOT** want to pass the identity function here, unless you know what
|
||||
/// you're doing, or you're within normalization code itself and will handle
|
||||
/// an unnormalized tail recursively.
|
||||
///
|
||||
/// See also `struct_tail_for_codegen`, which is suitable for use
|
||||
/// during codegen.
|
||||
pub fn struct_tail_with_normalize(
|
||||
pub fn struct_tail_raw(
|
||||
self,
|
||||
mut ty: Ty<'tcx>,
|
||||
mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
|
||||
@ -281,7 +275,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> (Ty<'tcx>, Ty<'tcx>) {
|
||||
let tcx = self;
|
||||
tcx.struct_lockstep_tails_with_normalize(source, target, |ty| {
|
||||
tcx.struct_lockstep_tails_raw(source, target, |ty| {
|
||||
tcx.normalize_erasing_regions(param_env, ty)
|
||||
})
|
||||
}
|
||||
@ -294,7 +288,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
///
|
||||
/// See also `struct_lockstep_tails_for_codegen`, which is suitable for use
|
||||
/// during codegen.
|
||||
pub fn struct_lockstep_tails_with_normalize(
|
||||
pub fn struct_lockstep_tails_raw(
|
||||
self,
|
||||
source: Ty<'tcx>,
|
||||
target: Ty<'tcx>,
|
||||
|
@ -687,10 +687,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
let mut applied_do_not_recommend = false;
|
||||
loop {
|
||||
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
|
||||
if self.tcx.has_attrs_with_path(
|
||||
c.impl_or_alias_def_id,
|
||||
&[sym::diagnostic, sym::do_not_recommend],
|
||||
) {
|
||||
if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) {
|
||||
let code = (*c.derived.parent_code).clone();
|
||||
obligation.cause.map_code(|_| code);
|
||||
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
|
||||
@ -1629,11 +1626,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
.tcx
|
||||
.all_impls(def_id)
|
||||
// ignore `do_not_recommend` items
|
||||
.filter(|def_id| {
|
||||
!self
|
||||
.tcx
|
||||
.has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend])
|
||||
})
|
||||
.filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
|
||||
// Ignore automatically derived impls and `!Trait` impls.
|
||||
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
|
||||
.filter_map(|header| {
|
||||
@ -1903,12 +1896,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
let impl_candidates = impl_candidates
|
||||
.into_iter()
|
||||
.cloned()
|
||||
.filter(|cand| {
|
||||
!self.tcx.has_attrs_with_path(
|
||||
cand.impl_def_id,
|
||||
&[sym::diagnostic, sym::do_not_recommend],
|
||||
)
|
||||
})
|
||||
.filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let def_id = trait_ref.def_id();
|
||||
|
@ -13,7 +13,6 @@ use rustc_middle::bug;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use super::delegate::SolverDelegate;
|
||||
use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||
@ -440,10 +439,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
||||
source: CandidateSource::Impl(impl_def_id),
|
||||
result: _,
|
||||
} = candidate.kind()
|
||||
&& goal
|
||||
.infcx()
|
||||
.tcx
|
||||
.has_attrs_with_path(impl_def_id, &[sym::diagnostic, sym::do_not_recommend])
|
||||
&& goal.infcx().tcx.do_not_recommend_impl(impl_def_id)
|
||||
{
|
||||
return ControlFlow::Break(self.obligation.clone());
|
||||
}
|
||||
|
@ -1110,7 +1110,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
| ty::Error(_) => false,
|
||||
}
|
||||
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
|
||||
let tail = selcx.tcx().struct_tail_with_normalize(
|
||||
let tail = selcx.tcx().struct_tail_raw(
|
||||
self_ty,
|
||||
|ty| {
|
||||
// We throw away any obligations we get from this, since we normalize
|
||||
@ -1149,10 +1149,10 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
| ty::Never
|
||||
// Extern types have unit metadata, according to RFC 2850
|
||||
| ty::Foreign(_)
|
||||
// If returned by `struct_tail_without_normalization` this is a unit struct
|
||||
// If returned by `struct_tail` this is a unit struct
|
||||
// without any fields, or not a struct, and therefore is Sized.
|
||||
| ty::Adt(..)
|
||||
// If returned by `struct_tail_without_normalization` this is the empty tuple.
|
||||
// If returned by `struct_tail` this is the empty tuple.
|
||||
| ty::Tuple(..)
|
||||
// Integers and floats are always Sized, and so have unit type metadata.
|
||||
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
|
||||
|
@ -219,9 +219,13 @@ fn layout_of_uncached<'tcx>(
|
||||
// its struct tail cannot be normalized either, so try to get a
|
||||
// more descriptive layout error here, which will lead to less confusing
|
||||
// diagnostics.
|
||||
//
|
||||
// We use the raw struct tail function here to get the first tail
|
||||
// that is an alias, which is likely the cause of the normalization
|
||||
// error.
|
||||
match tcx.try_normalize_erasing_regions(
|
||||
param_env,
|
||||
tcx.struct_tail_without_normalization(pointee),
|
||||
tcx.struct_tail_raw(pointee, |ty| ty, || {}),
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(better_err) => {
|
||||
|
@ -581,7 +581,7 @@ pub use core::fmt::Alignment;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::Error;
|
||||
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
|
||||
pub use core::fmt::FormatterFn;
|
||||
pub use core::fmt::{from_fn, FromFn};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{write, Arguments};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -1018,7 +1018,8 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
|
||||
/// Creates a type whose [`fmt::Debug`] and [`fmt::Display`] impls are provided with the function
|
||||
/// `f`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1030,17 +1031,25 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
||||
/// assert_eq!(format!("{}", value), "a");
|
||||
/// assert_eq!(format!("{:?}", value), "'a'");
|
||||
///
|
||||
/// let wrapped = fmt::FormatterFn(|f| write!(f, "{value:?}"));
|
||||
/// let wrapped = fmt::from_fn(|f| write!(f, "{value:?}"));
|
||||
/// assert_eq!(format!("{}", wrapped), "'a'");
|
||||
/// assert_eq!(format!("{:?}", wrapped), "'a'");
|
||||
/// ```
|
||||
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
|
||||
pub struct FormatterFn<F>(pub F)
|
||||
pub fn from_fn<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result>(f: F) -> FromFn<F> {
|
||||
FromFn(f)
|
||||
}
|
||||
|
||||
/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
|
||||
///
|
||||
/// Created with [`from_fn`].
|
||||
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
|
||||
pub struct FromFn<F>(F)
|
||||
where
|
||||
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
|
||||
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
|
||||
impl<F> fmt::Debug for FormatterFn<F>
|
||||
impl<F> fmt::Debug for FromFn<F>
|
||||
where
|
||||
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
|
||||
{
|
||||
@ -1050,7 +1059,7 @@ where
|
||||
}
|
||||
|
||||
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
|
||||
impl<F> fmt::Display for FormatterFn<F>
|
||||
impl<F> fmt::Display for FromFn<F>
|
||||
where
|
||||
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ pub enum Alignment {
|
||||
}
|
||||
|
||||
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
|
||||
pub use self::builders::FormatterFn;
|
||||
pub use self::builders::{from_fn, FromFn};
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
|
||||
|
||||
|
@ -434,7 +434,7 @@ impl Miri {
|
||||
builder: &Builder<'_>,
|
||||
compiler: Compiler,
|
||||
target: TargetSelection,
|
||||
) -> String {
|
||||
) -> PathBuf {
|
||||
let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysroot");
|
||||
let mut cargo = builder::Cargo::new(
|
||||
builder,
|
||||
@ -467,7 +467,7 @@ impl Miri {
|
||||
// Output is "<sysroot>\n".
|
||||
let sysroot = stdout.trim_end();
|
||||
builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
|
||||
sysroot.to_owned()
|
||||
PathBuf::from(sysroot)
|
||||
}
|
||||
}
|
||||
|
||||
@ -520,12 +520,14 @@ impl Step for Miri {
|
||||
builder.ensure(compile::Std::new(target_compiler, host));
|
||||
let host_sysroot = builder.sysroot(target_compiler);
|
||||
|
||||
// Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared
|
||||
// properly when rustc changes. Similar to `Builder::cargo`, we skip this in dry runs to
|
||||
// make sure the relevant compiler has been set up properly.
|
||||
// Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared when
|
||||
// the sysroot gets rebuilt, to avoid "found possibly newer version of crate `std`" errors.
|
||||
if !builder.config.dry_run() {
|
||||
let ui_test_dep_dir = builder.stage_out(host_compiler, Mode::ToolStd).join("miri_ui");
|
||||
builder.clear_if_dirty(&ui_test_dep_dir, &builder.rustc(host_compiler));
|
||||
// The mtime of `miri_sysroot` changes when the sysroot gets rebuilt (also see
|
||||
// <https://github.com/RalfJung/rustc-build-sysroot/commit/10ebcf60b80fe2c3dc765af0ff19fdc0da4b7466>).
|
||||
// We can hence use that directly as a signal to clear the ui test dir.
|
||||
builder.clear_if_dirty(&ui_test_dep_dir, &miri_sysroot);
|
||||
}
|
||||
|
||||
// Run `cargo test`.
|
||||
|
@ -1,23 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
# Usage: $0 project_name url sha1
|
||||
# Get the crate with the specified sha1.
|
||||
#
|
||||
# all arguments are required.
|
||||
#
|
||||
# See below link for git usage:
|
||||
# https://stackoverflow.com/questions/3489173#14091182
|
||||
|
||||
# Mandatory arguments:
|
||||
PROJECT_NAME=$1
|
||||
URL=$2
|
||||
SHA1=$3
|
||||
|
||||
function err_exit() {
|
||||
echo "ERROR:" $*
|
||||
exit 1
|
||||
}
|
||||
|
||||
git clone $URL $PROJECT_NAME || err_exit
|
||||
cd $PROJECT_NAME || err_exit
|
||||
git reset --hard $SHA1 || err_exit
|
@ -1,5 +1,5 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:21:17
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17
|
||||
|
|
||||
LL | fn m<'a>() {
|
||||
| -- lifetime `'a` defined here
|
@ -0,0 +1,15 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17
|
||||
|
|
||||
LL | fn m<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let unsend: *const dyn Cat<'a> = &();
|
||||
LL | let _send = unsend as *const S<dyn Cat<'static>>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
|
|
||||
= note: requirement occurs because of the type `S<dyn Cat<'_>>`, which makes the generic argument `dyn Cat<'_>` invariant
|
||||
= note: the struct `S<T>` is invariant over the parameter `T`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,3 +1,6 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-fail
|
||||
//
|
||||
// Make sure we can't trick the compiler by using a projection.
|
||||
|
@ -0,0 +1,21 @@
|
||||
#![allow(unknown_or_malformed_diagnostic_attributes)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
impl<A> Foo for (A,) {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
impl<A, B> Foo for (A, B) {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
impl<A, B, C> Foo for (A, B, C) {}
|
||||
|
||||
impl Foo for i32 {}
|
||||
|
||||
fn check(a: impl Foo) {}
|
||||
|
||||
fn main() {
|
||||
check(());
|
||||
//~^ ERROR the trait bound `(): Foo` is not satisfied
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
error[E0277]: the trait bound `(): Foo` is not satisfied
|
||||
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:11
|
||||
|
|
||||
LL | check(());
|
||||
| ----- ^^ the trait `Foo` is not implemented for `()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `Foo`:
|
||||
(A, B)
|
||||
(A, B, C)
|
||||
(A,)
|
||||
note: required by a bound in `check`
|
||||
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:16:18
|
||||
|
|
||||
LL | fn check(a: impl Foo) {}
|
||||
| ^^^ required by this bound in `check`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user