Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-10-31 05:03:37 +00:00
commit 482859261a
444 changed files with 5150 additions and 3511 deletions

View file

@ -175,9 +175,7 @@ fn main() {
// Find any host flags that were passed by bootstrap.
// The flags are stored in a RUSTC_HOST_FLAGS variable, separated by spaces.
if let Ok(flags) = std::env::var("RUSTC_HOST_FLAGS") {
for flag in flags.split(' ') {
cmd.arg(flag);
}
cmd.args(flags.split(' '));
}
}

View file

@ -153,7 +153,6 @@ impl Step for Std {
// NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so
// its artifacts can't be reused.
&& compiler.stage != 0
// This check is specific to testing std itself; see `test::Std` for more details.
&& !self.force_recompile
{
let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });

View file

@ -2767,25 +2767,32 @@ impl Config {
}
};
let files_to_track =
&["compiler", "library", "src/version", "src/stage0", "src/ci/channel"];
let mut files_to_track = vec!["compiler", "src/version", "src/stage0", "src/ci/channel"];
// In CI, disable ci-rustc if there are changes in the library tree. But for non-CI, ignore
// these changes to speed up the build process for library developers. This provides consistent
// functionality for library developers between `download-rustc=true` and `download-rustc="if-unchanged"`
// options.
if CiEnv::is_ci() {
files_to_track.push("library");
}
// Look for a version to compare to based on the current commit.
// Only commits merged by bors will have CI artifacts.
let commit = match self.last_modified_commit(files_to_track, "download-rustc", if_unchanged)
{
Some(commit) => commit,
None => {
if if_unchanged {
return None;
let commit =
match self.last_modified_commit(&files_to_track, "download-rustc", if_unchanged) {
Some(commit) => commit,
None => {
if if_unchanged {
return None;
}
println!("ERROR: could not find commit hash for downloading rustc");
println!("HELP: maybe your repository history is too shallow?");
println!("HELP: consider disabling `download-rustc`");
println!("HELP: or fetch enough history to include one upstream commit");
crate::exit!(1);
}
println!("ERROR: could not find commit hash for downloading rustc");
println!("HELP: maybe your repository history is too shallow?");
println!("HELP: consider disabling `download-rustc`");
println!("HELP: or fetch enough history to include one upstream commit");
crate::exit!(1);
}
};
};
if CiEnv::is_ci() && {
let head_sha =

View file

@ -6,8 +6,8 @@ Rust for AIX operating system, currently only 64-bit PowerPC is supported.
## Target maintainers
- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises
- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq
- David Tenty `daltenty@ibm.com`, https://github.com/daltenty
- Chris Cambly, `ccambly@ca.ibm.com`, https://github.com/gilamn5tr
## Requirements

View file

@ -7,17 +7,9 @@ updatable, and performant.
## Target maintainers
The [Fuchsia team]:
See [`fuchsia.toml`] in the `team` repository for current target maintainers.
- Tyler Mandry ([@tmandry](https://github.com/tmandry))
- David Koloski ([@djkoloski](https://github.com/djkoloski))
- Julia Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
- Erick Tryzelaar ([@erickt](https://github.com/erickt))
As the team evolves over time, the specific members listed here may differ from
the members reported by the API. The API should be considered to be
authoritative if this occurs. Instead of pinging individual members, use
`@rustbot ping fuchsia` to contact the team on GitHub.
[`fuchsia.toml`]: https://github.com/rust-lang/team/blob/master/teams/fuchsia.toml
## Table of contents

View file

@ -1,7 +1,7 @@
use rustc_hir as hir;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt};
use rustc_infer::traits;
use rustc_middle::ty::{self, Upcast};
use rustc_middle::ty::{self, TypingMode, Upcast};
use rustc_span::DUMMY_SP;
use rustc_span::def_id::DefId;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@ -38,7 +38,7 @@ pub(crate) fn synthesize_blanket_impls(
if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
continue;
}
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let args = infcx.fresh_args_for_item(DUMMY_SP, item_def_id);
let impl_ty = ty.instantiate(tcx, args);
let param_env = ty::ParamEnv::empty();

View file

@ -45,7 +45,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
use rustc_hir_analysis::lower_ty;
use rustc_middle::metadata::Reexport;
use rustc_middle::middle::resolve_bound_vars as rbv;
use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_middle::{bug, span_bug};
use rustc_span::ExpnKind;
use rustc_span::hygiene::{AstPass, MacroKind};
@ -1829,7 +1829,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
Array(Box::new(clean_ty(ty, cx)), length.into())
}
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
TyKind::OpaqueDef(ty, _) => {
TyKind::OpaqueDef(ty) => {
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
}
TyKind::Path(_) => clean_qpath(ty, cx),
@ -1863,7 +1863,7 @@ fn normalize<'tcx>(
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
// Try to normalize `<X as Y>::T` to a type
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let normalized = infcx
.at(&ObligationCause::dummy(), cx.param_env)
.query_normalize(ty)
@ -2399,7 +2399,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>(
use rustc_trait_selection::infer::TyCtxtInferExt;
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let kind = match variant.ctor_kind() {
Some(CtorKind::Const) => VariantKind::CLike,
Some(CtorKind::Fn) => VariantKind::Tuple(

View file

@ -198,10 +198,6 @@ fn generate_mergeable_doctest(
} else {
writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
.unwrap();
if scraped_test.langstr.no_run {
// To prevent having warnings about unused items since they're not called.
writeln!(output, "#![allow(unused)]").unwrap();
}
if doctest.has_main_fn {
output.push_str(&doctest.everything_else);
} else {

View file

@ -113,7 +113,19 @@ impl<'tcx> HirCollector<'tcx> {
let attrs = Attributes::from_ast(ast_attrs);
if let Some(doc) = attrs.opt_doc_value() {
let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
self.collector.position = span;
self.collector.position = if span.edition().at_least_rust_2024() {
span
} else {
// this span affects filesystem path resolution,
// so we need to keep it the same as it was previously
ast_attrs
.iter()
.find(|attr| attr.doc_str().is_some())
.map(|attr| {
attr.span.ctxt().outer_expn().expansion_cause().unwrap_or(attr.span)
})
.unwrap_or(DUMMY_SP)
};
markdown::find_testable_code(
&doc,
&mut self.collector,

View file

@ -20,8 +20,7 @@ use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_metadata::creader::{CStore, LoadedMacro};
use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, TyCtxt, TypingMode};
use rustc_span::symbol::kw;
use rustc_span::{Symbol, sym};
use rustc_target::spec::abi::Abi;
@ -613,7 +612,7 @@ fn generate_item_def_id_path(
// No need to try to infer the actual parent item if it's not an associated item from the `impl`
// block.
if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
def_id = infcx
.at(&ObligationCause::dummy(), tcx.param_env(def_id))
.query_normalize(ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()))

View file

@ -9,7 +9,8 @@ use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Saf
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{
self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults,
self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt,
TypeckResults,
};
use rustc_session::declare_lint_pass;
use rustc_span::symbol::sym;
@ -203,7 +204,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
// 'cuz currently nothing changes after deleting this check.
local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
}) {
match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
match cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().type_implements_fn_trait(
cx.param_env,
Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
ty::PredicatePolarity::Positive,

View file

@ -117,7 +117,7 @@ fn check_needless_must_use(
} else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
// Ignore async functions unless Future::Output type is a must_use type
if sig.header.is_async() {
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
if let Some(future_ty) = infcx.err_ctxt().get_impl_future_output_ty(return_ty(cx, item_id))
&& !is_must_use_ty(cx, future_ty)
{

View file

@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
if is_future {
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
let span = decl.output.span();
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let cause = traits::ObligationCause::misc(span, fn_def_id);
ocx.register_bound(cause, cx.param_env, ret_ty, send_trait);

View file

@ -420,15 +420,6 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> {
fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
match ty.kind {
TyKind::OpaqueDef(opaque, bounds) => {
let len = self.lts.len();
self.visit_opaque_ty(opaque);
self.lts.truncate(len);
self.lts.extend(bounds.iter().filter_map(|bound| match bound {
GenericArg::Lifetime(&l) => Some(l),
_ => None,
}));
},
TyKind::BareFn(&BareFnTy { decl, .. }) => {
let mut sub_visitor = RefVisitor::new(self.cx);
sub_visitor.visit_fn_decl(decl);

View file

@ -4,9 +4,11 @@ use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl,
FnRetTy, GenericArg, GenericBound, ImplItem, Item, LifetimeName, Node, TraitRef, Ty, TyKind,
FnRetTy, GenericBound, ImplItem, Item, Node, OpaqueTy, TraitRef, Ty, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
use rustc_middle::ty;
use rustc_session::declare_lint_pass;
use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, sym};
@ -44,21 +46,22 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
decl: &'tcx FnDecl<'_>,
body: &'tcx Body<'_>,
span: Span,
def_id: LocalDefId,
fn_def_id: LocalDefId,
) {
if let Some(header) = kind.header()
&& !header.asyncness.is_async()
// Check that this function returns `impl Future`
&& let FnRetTy::Return(ret_ty) = decl.output
&& let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty)
&& let TyKind::OpaqueDef(opaque) = ret_ty.kind
&& let Some(trait_ref) = future_trait_ref(cx, opaque)
&& let Some(output) = future_output_ty(trait_ref)
&& captures_all_lifetimes(decl.inputs, &output_lifetimes)
&& captures_all_lifetimes(cx, fn_def_id, opaque.def_id)
// Check that the body of the function consists of one async block
&& let ExprKind::Block(block, _) = body.value.kind
&& block.stmts.is_empty()
&& let Some(closure_body) = desugared_async_block(cx, block)
&& let Node::Item(Item {vis_span, ..}) | Node::ImplItem(ImplItem {vis_span, ..}) =
cx.tcx.hir_node_by_def_id(def_id)
cx.tcx.hir_node_by_def_id(fn_def_id)
{
let header_span = span.with_hi(ret_ty.span.hi());
@ -101,12 +104,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
}
}
fn future_trait_ref<'tcx>(
cx: &LateContext<'tcx>,
ty: &'tcx Ty<'tcx>,
) -> Option<(&'tcx TraitRef<'tcx>, Vec<LifetimeName>)> {
if let TyKind::OpaqueDef(opaque, bounds) = ty.kind
&& let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
fn future_trait_ref<'tcx>(cx: &LateContext<'tcx>, opaque: &'tcx OpaqueTy<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
if let Some(trait_ref) = opaque.bounds.iter().find_map(|bound| {
if let GenericBound::Trait(poly) = bound {
Some(&poly.trait_ref)
} else {
@ -115,18 +114,7 @@ fn future_trait_ref<'tcx>(
})
&& trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait()
{
let output_lifetimes = bounds
.iter()
.filter_map(|bound| {
if let GenericArg::Lifetime(lt) = bound {
Some(lt.res)
} else {
None
}
})
.collect();
return Some((trait_ref, output_lifetimes));
return Some(trait_ref);
}
None
@ -145,27 +133,35 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
None
}
fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) -> bool {
let input_lifetimes: Vec<LifetimeName> = inputs
.iter()
.filter_map(|ty| {
if let TyKind::Ref(lt, _) = ty.kind {
Some(lt.res)
} else {
None
}
})
.collect();
fn captures_all_lifetimes(cx: &LateContext<'_>, fn_def_id: LocalDefId, opaque_def_id: LocalDefId) -> bool {
let early_input_params = ty::GenericArgs::identity_for_item(cx.tcx, fn_def_id);
let late_input_params = cx.tcx.late_bound_vars(cx.tcx.local_def_id_to_hir_id(fn_def_id));
// The lint should trigger in one of these cases:
// - There are no input lifetimes
// - There's only one output lifetime bound using `+ '_`
// - All input lifetimes are explicitly bound to the output
input_lifetimes.is_empty()
|| (output_lifetimes.len() == 1 && matches!(output_lifetimes[0], LifetimeName::Infer))
|| input_lifetimes
.iter()
.all(|in_lt| output_lifetimes.iter().any(|out_lt| in_lt == out_lt))
let num_early_lifetimes = early_input_params
.iter()
.filter(|param| param.as_region().is_some())
.count();
let num_late_lifetimes = late_input_params
.iter()
.filter(|param_kind| matches!(param_kind, ty::BoundVariableKind::Region(_)))
.count();
// There is no lifetime, so they are all captured.
if num_early_lifetimes == 0 && num_late_lifetimes == 0 {
return true;
}
// By construction, each captured lifetime only appears once in `opaque_captured_lifetimes`.
let num_captured_lifetimes = cx
.tcx
.opaque_captured_lifetimes(opaque_def_id)
.iter()
.filter(|&(lifetime, _)| match *lifetime {
ResolvedArg::EarlyBound(_) | ResolvedArg::LateBound(ty::INNERMOST, _, _) => true,
_ => false,
})
.count();
num_captured_lifetimes == num_early_lifetimes + num_late_lifetimes
}
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {

View file

@ -568,7 +568,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
!cx.tcx
.infer_ctxt()
.build()
.build(cx.typing_mode())
.predicate_must_hold_modulo_regions(&obligation)
}) {
return false;

View file

@ -278,7 +278,7 @@ fn needless_borrow_count<'tcx>(
let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, &args_with_referent_ty[..]);
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
infcx.predicate_must_hold_modulo_regions(&obligation)
})
};

View file

@ -160,7 +160,7 @@ impl NoEffect {
// Remove `impl Future<Output = T>` to get `T`
if cx.tcx.ty_is_opaque_future(ret_ty)
&& let Some(true_ret_ty) =
cx.tcx.infer_ctxt().build().err_ctxt().get_impl_future_output_ty(ret_ty)
cx.tcx.infer_ctxt().build(cx.typing_mode()).err_ctxt().get_impl_future_output_ty(ret_ty)
{
ret_ty = true_ret_ty;
}

View file

@ -695,7 +695,7 @@ fn matches_preds<'tcx>(
ty: Ty<'tcx>,
preds: &'tcx [ty::PolyExistentialPredicate<'tcx>],
) -> bool {
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(cx.typing_mode());
preds
.iter()
.all(|&p| match cx.tcx.instantiate_bound_regions_with_erased(p) {

View file

@ -114,7 +114,7 @@ fn into_iter_bound<'tcx>(
if !cx
.tcx
.infer_ctxt()
.build()
.build(cx.typing_mode())
.predicate_must_hold_modulo_regions(&obligation)
{
return None;

View file

@ -1231,16 +1231,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
},
TyKind::Path(ref qpath) => self.hash_qpath(qpath),
TyKind::OpaqueDef(_, arg_list) => {
self.hash_generic_args(arg_list);
},
TyKind::TraitObject(_, lifetime, _) => {
self.hash_lifetime(lifetime);
},
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
},
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::AnonAdt(_) => {},
TyKind::Err(_) | TyKind::Infer | TyKind::Never | TyKind::InferDelegation(..) | TyKind::OpaqueDef(_) | TyKind::AnonAdt(_) => {},
}
}

View file

@ -185,9 +185,7 @@ impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
vis.into_map(cx)
};
let maybe_storage_live_result = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len())))
.into_engine(cx.tcx, mir)
.pass_name("redundant_clone")
.iterate_to_fixpoint()
.iterate_to_fixpoint(cx.tcx, mir, Some("redundant_clone"))
.into_results_cursor(mir);
let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
vis.visit_body(mir);

View file

@ -17,7 +17,7 @@ use rustc_middle::mir::{
};
use rustc_middle::traits::{BuiltinImplSource, ImplSource, ObligationCause};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt};
use rustc_middle::ty::{self, GenericArgKind, TraitRef, Ty, TyCtxt, TypingMode};
use rustc_span::Span;
use rustc_span::symbol::sym;
use rustc_trait_selection::traits::{ObligationCtxt, SelectionContext};
@ -420,7 +420,7 @@ fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>
TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
);
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(obligation.param_env));
let mut selcx = SelectionContext::new(&infcx);
let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
return false;

View file

@ -19,7 +19,7 @@ use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{
self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind,
GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, TypingMode,
};
use rustc_span::symbol::Ident;
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
@ -268,7 +268,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
return false;
}
let infcx = tcx.infer_ctxt().build();
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
let args = args
.into_iter()
.map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into()))
@ -362,7 +362,7 @@ fn is_normalizable_helper<'tcx>(
}
// prevent recursive loops, false-negative is better than endless loop leading to stack overflow
cache.insert(ty, false);
let infcx = cx.tcx.infer_ctxt().build();
let infcx = cx.tcx.infer_ctxt().build(TypingMode::from_param_env(param_env));
let cause = ObligationCause::dummy();
let result = if infcx.at(&cause, param_env).query_normalize(ty).is_ok() {
match ty.kind() {
@ -1268,7 +1268,7 @@ pub fn make_normalized_projection_with_regions<'tcx>(
let cause = ObligationCause::dummy();
match tcx
.infer_ctxt()
.build()
.build(TypingMode::from_param_env(param_env))
.at(&cause, param_env)
.query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args))
{
@ -1284,7 +1284,7 @@ pub fn make_normalized_projection_with_regions<'tcx>(
pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
let cause = ObligationCause::dummy();
match tcx.infer_ctxt().build().at(&cause, param_env).query_normalize(ty) {
match tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)).at(&cause, param_env).query_normalize(ty) {
Ok(ty) => ty.value,
Err(_) => ty,
}

View file

@ -11,7 +11,7 @@ error: the following explicit lifetimes could be elided: 'a
--> tests/ui/issue_4266.rs:10:21
|
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
| ^^ ^^
| ^^ ^^ ^^
error: methods called `new` usually take no `self`
--> tests/ui/issue_4266.rs:31:22

View file

@ -18,6 +18,7 @@ build_helper = { path = "../build_helper" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
regex = "1.0"
semver = { version = "1.0.23", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rustfix = "0.8.1"

View file

@ -7,6 +7,7 @@ use std::sync::OnceLock;
use std::{fmt, iter};
use build_helper::git::GitConfig;
use semver::Version;
use serde::de::{Deserialize, Deserializer, Error as _};
use test::{ColorConfig, OutputFormat};
@ -298,7 +299,7 @@ pub struct Config {
pub lldb_version: Option<u32>,
/// Version of LLVM
pub llvm_version: Option<u32>,
pub llvm_version: Option<Version>,
/// Is LLVM a system LLVM
pub system_llvm: bool,

View file

@ -6,6 +6,7 @@ use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;
use semver::Version;
use tracing::*;
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
@ -1113,26 +1114,39 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
Some((regex, replacement))
}
pub fn extract_llvm_version(version: &str) -> Option<u32> {
let pat = |c: char| !c.is_ascii_digit() && c != '.';
let version_without_suffix = match version.find(pat) {
Some(pos) => &version[..pos],
/// Given an llvm version string that looks like `1.2.3-rc1`, extract as semver. Note that this
/// accepts more than just strict `semver` syntax (as in `major.minor.patch`); this permits omitting
/// minor and patch version components so users can write e.g. `//@ min-llvm-version: 19` instead of
/// having to write `//@ min-llvm-version: 19.0.0`.
///
/// Currently panics if the input string is malformed, though we really should not use panic as an
/// error handling strategy.
///
/// FIXME(jieyouxu): improve error handling
pub fn extract_llvm_version(version: &str) -> Version {
// The version substring we're interested in usually looks like the `1.2.3`, without any of the
// fancy suffix like `-rc1` or `meow`.
let version = version.trim();
let uninterested = |c: char| !c.is_ascii_digit() && c != '.';
let version_without_suffix = match version.split_once(uninterested) {
Some((prefix, _suffix)) => prefix,
None => version,
};
let components: Vec<u32> = version_without_suffix
let components: Vec<u64> = version_without_suffix
.split('.')
.map(|s| s.parse().expect("Malformed version component"))
.map(|s| s.parse().expect("llvm version component should consist of only digits"))
.collect();
let version = match *components {
[a] => a * 10_000,
[a, b] => a * 10_000 + b * 100,
[a, b, c] => a * 10_000 + b * 100 + c,
_ => panic!("Malformed version"),
};
Some(version)
match &components[..] {
[major] => Version::new(*major, 0, 0),
[major, minor] => Version::new(*major, *minor, 0),
[major, minor, patch] => Version::new(*major, *minor, *patch),
_ => panic!("malformed llvm version string, expected only 1-3 components: {version}"),
}
}
pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
let output = Command::new(binary_path).arg("--version").output().ok()?;
if !output.status.success() {
return None;
@ -1140,7 +1154,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
let version = String::from_utf8(output.stdout).ok()?;
for line in version.lines() {
if let Some(version) = line.split("LLVM version ").nth(1) {
return extract_llvm_version(version);
return Some(extract_llvm_version(version));
}
}
None
@ -1247,15 +1261,17 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
false
}
/// Takes a directive of the form `"<version1> [- <version2>]"`,
/// returns the numeric representation of `<version1>` and `<version2>` as
/// tuple: `(<version1> as u32, <version2> as u32)`.
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
///
/// If the `<version2>` part is omitted, the second component of the tuple
/// is the same as `<version1>`.
fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
/// If the `<version2>` part is omitted, the second component of the tuple is the same as
/// `<version1>`.
fn extract_version_range<'a, F, VersionTy: Clone>(
line: &'a str,
parse: F,
) -> Option<(VersionTy, VersionTy)>
where
F: Fn(&str) -> Option<u32>,
F: Fn(&'a str) -> Option<VersionTy>,
{
let mut splits = line.splitn(2, "- ").map(str::trim);
let min = splits.next().unwrap();
@ -1273,7 +1289,7 @@ where
let max = match max {
Some("") => return None,
Some(max) => parse(max)?,
_ => min,
_ => min.clone(),
};
Some((min, max))
@ -1489,43 +1505,55 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
};
}
}
if let Some(actual_version) = config.llvm_version {
if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if actual version is smaller the minimum required
// version
if actual_version < min_version {
if let Some(actual_version) = &config.llvm_version {
// Note that these `min` versions will check for not just major versions.
if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") {
let min_version = extract_llvm_version(&version_string);
// Ignore if actual version is smaller than the minimum required version.
if *actual_version < min_version {
return IgnoreDecision::Ignore {
reason: format!("ignored when the LLVM version is older than {rest}"),
reason: format!(
"ignored when the LLVM version {actual_version} is older than {min_version}"
),
};
}
} else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
} else if let Some(version_string) =
config.parse_name_value_directive(line, "min-system-llvm-version")
{
let min_version = extract_llvm_version(&version_string);
// Ignore if using system LLVM and actual version
// is smaller the minimum required version
if config.system_llvm && actual_version < min_version {
if config.system_llvm && *actual_version < min_version {
return IgnoreDecision::Ignore {
reason: format!("ignored when the system LLVM version is older than {rest}"),
reason: format!(
"ignored when the system LLVM version {actual_version} is older than {min_version}"
),
};
}
} else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
} else if let Some(version_range) =
config.parse_name_value_directive(line, "ignore-llvm-version")
{
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
let (v_min, v_max) =
extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
extract_version_range(&version_range, |s| Some(extract_llvm_version(s)))
.unwrap_or_else(|| {
panic!("couldn't parse version range: \"{version_range}\"");
});
if v_max < v_min {
panic!("Malformed LLVM version range: max < min")
panic!("malformed LLVM version range where {v_max} < {v_min}")
}
// Ignore if version lies inside of range.
if actual_version >= v_min && actual_version <= v_max {
if *actual_version >= v_min && *actual_version <= v_max {
if v_min == v_max {
return IgnoreDecision::Ignore {
reason: format!("ignored when the LLVM version is {rest}"),
reason: format!("ignored when the LLVM version is {actual_version}"),
};
} else {
return IgnoreDecision::Ignore {
reason: format!("ignored when the LLVM version is between {rest}"),
reason: format!(
"ignored when the LLVM version is between {v_min} and {v_max}"
),
};
}
}

View file

@ -1,9 +1,13 @@
use std::io::Read;
use std::path::Path;
use super::iter_header;
use semver::Version;
use super::{
EarlyProps, HeadersCache, extract_llvm_version, extract_version_range, iter_header,
parse_normalize_rule,
};
use crate::common::{Config, Debugger, Mode};
use crate::header::{EarlyProps, HeadersCache, parse_normalize_rule};
fn make_test_description<R: Read>(
config: &Config,
@ -408,18 +412,66 @@ fn channel() {
}
#[test]
fn test_extract_version_range() {
use super::{extract_llvm_version, extract_version_range};
fn test_extract_llvm_version() {
// Note: officially, semver *requires* that versions at the minimum have all three
// `major.minor.patch` numbers, though for test-writer's convenience we allow omitting the minor
// and patch numbers (which will be stubbed out as 0).
assert_eq!(extract_llvm_version("0"), Version::new(0, 0, 0));
assert_eq!(extract_llvm_version("0.0"), Version::new(0, 0, 0));
assert_eq!(extract_llvm_version("0.0.0"), Version::new(0, 0, 0));
assert_eq!(extract_llvm_version("1"), Version::new(1, 0, 0));
assert_eq!(extract_llvm_version("1.2"), Version::new(1, 2, 0));
assert_eq!(extract_llvm_version("1.2.3"), Version::new(1, 2, 3));
assert_eq!(extract_llvm_version("4.5.6git"), Version::new(4, 5, 6));
assert_eq!(extract_llvm_version("4.5.6-rc1"), Version::new(4, 5, 6));
assert_eq!(extract_llvm_version("123.456.789-rc1"), Version::new(123, 456, 789));
assert_eq!(extract_llvm_version("8.1.2-rust"), Version::new(8, 1, 2));
assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Version::new(9, 0, 1));
assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Version::new(9, 3, 1));
assert_eq!(extract_llvm_version("10.0.0-rust"), Version::new(10, 0, 0));
assert_eq!(extract_llvm_version("11.1.0"), Version::new(11, 1, 0));
assert_eq!(extract_llvm_version("12.0.0libcxx"), Version::new(12, 0, 0));
assert_eq!(extract_llvm_version("12.0.0-rc3"), Version::new(12, 0, 0));
assert_eq!(extract_llvm_version("13.0.0git"), Version::new(13, 0, 0));
}
assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506)));
assert_eq!(extract_version_range("0 - 4.5.6", extract_llvm_version), Some((0, 40506)));
assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None);
assert_eq!(extract_version_range("-", extract_llvm_version), None);
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
assert_eq!(extract_version_range("0 -", extract_llvm_version), None);
#[test]
#[should_panic]
fn test_llvm_version_invalid_components() {
extract_llvm_version("4.x.6");
}
#[test]
#[should_panic]
fn test_llvm_version_invalid_prefix() {
extract_llvm_version("meow4.5.6");
}
#[test]
#[should_panic]
fn test_llvm_version_too_many_components() {
extract_llvm_version("4.5.6.7");
}
#[test]
fn test_extract_version_range() {
let wrapped_extract = |s: &str| Some(extract_llvm_version(s));
assert_eq!(
extract_version_range("1.2.3 - 4.5.6", wrapped_extract),
Some((Version::new(1, 2, 3), Version::new(4, 5, 6)))
);
assert_eq!(
extract_version_range("0 - 4.5.6", wrapped_extract),
Some((Version::new(0, 0, 0), Version::new(4, 5, 6)))
);
assert_eq!(extract_version_range("1.2.3 -", wrapped_extract), None);
assert_eq!(extract_version_range("1.2.3 - ", wrapped_extract), None);
assert_eq!(extract_version_range("- 4.5.6", wrapped_extract), None);
assert_eq!(extract_version_range("-", wrapped_extract), None);
assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
assert_eq!(extract_version_range("0 -", wrapped_extract), None);
}
#[test]

View file

@ -228,7 +228,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
};
let llvm_version =
matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
matches.opt_str("llvm-version").as_deref().map(header::extract_llvm_version).or_else(
|| header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
);

View file

@ -1,7 +1,6 @@
use std::ffi::OsString;
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
use crate::header::extract_llvm_version;
use crate::is_test;
#[test]
@ -67,15 +66,3 @@ fn is_test_test() {
assert!(!is_test(&OsString::from("#a_dog_gif")));
assert!(!is_test(&OsString::from("~a_temp_file")));
}
#[test]
fn test_extract_llvm_version() {
assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102));
assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
assert_eq!(extract_llvm_version("11.1.0"), Some(110100));
assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000));
assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000));
assert_eq!(extract_llvm_version("13.0.0git"), Some(130000));
}

View file

@ -9,11 +9,11 @@ use std::cell::RefCell;
use std::fmt::Write;
use std::{cmp, mem};
use rustc_abi::{BackendRepr, Size};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::{Mutability, RetagKind};
use rustc_middle::ty::layout::HasParamEnv;
use rustc_middle::ty::{self, Ty};
use rustc_target::abi::{Abi, Size};
use self::diagnostics::{RetagCause, RetagInfo};
pub use self::item::{Item, Permission};
@ -972,7 +972,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
RetagFields::OnlyScalar => {
// Matching `ArgAbi::new` at the time of writing, only fields of
// `Scalar` and `ScalarPair` ABI are considered.
matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
matches!(
place.layout.backend_repr,
BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
)
}
};
if recurse {

View file

@ -1,8 +1,8 @@
use rustc_abi::{BackendRepr, Size};
use rustc_middle::mir::{Mutability, RetagKind};
use rustc_middle::ty::layout::HasParamEnv;
use rustc_middle::ty::{self, Ty};
use rustc_span::def_id::DefId;
use rustc_target::abi::{Abi, Size};
use crate::borrow_tracker::{GlobalState, GlobalStateInner, ProtectorKind};
use crate::concurrency::data_race::NaReadType;
@ -495,7 +495,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
RetagFields::OnlyScalar => {
// Matching `ArgAbi::new` at the time of writing, only fields of
// `Scalar` and `ScalarPair` ABI are considered.
matches!(place.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..))
matches!(
place.layout.backend_repr,
BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
)
}
};
if recurse {

View file

@ -349,8 +349,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
i: impl Into<i128>,
dest: &impl Writeable<'tcx, Provenance>,
) -> InterpResult<'tcx> {
assert!(dest.layout().abi.is_scalar(), "write_int on non-scalar type {}", dest.layout().ty);
let val = if dest.layout().abi.is_signed() {
assert!(
dest.layout().backend_repr.is_scalar(),
"write_int on non-scalar type {}",
dest.layout().ty
);
let val = if dest.layout().backend_repr.is_signed() {
Scalar::from_int(i, dest.layout().size)
} else {
// `unwrap` can only fail here if `i` is negative

View file

@ -55,6 +55,7 @@ extern crate either;
extern crate tracing;
// The rustc crates we need
extern crate rustc_abi;
extern crate rustc_apfloat;
extern crate rustc_ast;
extern crate rustc_attr;

View file

@ -23,7 +23,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
interp_ok(match bin_op {
Eq | Ne | Lt | Le | Gt | Ge => {
assert_eq!(left.layout.abi, right.layout.abi); // types can differ, e.g. fn ptrs with different `for`
assert_eq!(left.layout.backend_repr, right.layout.backend_repr); // types can differ, e.g. fn ptrs with different `for`
let size = this.pointer_size();
// Just compare the bits. ScalarPairs are compared lexicographically.
// We thus always compare pairs and simply fill scalars up with 0.

View file

@ -5,7 +5,7 @@ use libffi::high::call as ffi;
use libffi::low::CodePtr;
use rustc_middle::ty::{self as ty, IntTy, UintTy};
use rustc_span::Symbol;
use rustc_target::abi::{Abi, HasDataLayout};
use rustc_abi::{BackendRepr, HasDataLayout};
use crate::*;
@ -149,7 +149,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Get the function arguments, and convert them to `libffi`-compatible form.
let mut libffi_args = Vec::<CArg>::with_capacity(args.len());
for arg in args.iter() {
if !matches!(arg.layout.abi, Abi::Scalar(_)) {
if !matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
throw_unsup_format!("only scalar argument types are support for native calls")
}
libffi_args.push(imm_to_carg(this.read_immediate(arg)?, this)?);

View file

@ -6,7 +6,7 @@ use base_db::ra_salsa::Cycle;
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
use hir_def::{
layout::{
Abi, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData,
BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData,
Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
},
LocalFieldId, StructId,
@ -168,7 +168,7 @@ fn layout_of_simd_ty(
// Compute the ABI of the element type:
let e_ly = db.layout_of_ty(e_ty, env)?;
let Abi::Scalar(e_abi) = e_ly.abi else {
let BackendRepr::Scalar(e_abi) = e_ly.backend_repr else {
return Err(LayoutError::Unknown);
};
@ -190,7 +190,7 @@ fn layout_of_simd_ty(
Ok(Arc::new(Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields,
abi: Abi::Vector { element: e_abi, count: e_len },
backend_repr: BackendRepr::Vector { element: e_abi, count: e_len },
largest_niche: e_ly.largest_niche,
size,
align,
@ -294,10 +294,10 @@ pub fn layout_of_ty_query(
.checked_mul(count, dl)
.ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
let abi = if count != 0 && matches!(element.abi, Abi::Uninhabited) {
Abi::Uninhabited
let backend_repr = if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) {
BackendRepr::Uninhabited
} else {
Abi::Aggregate { sized: true }
BackendRepr::Memory { sized: true }
};
let largest_niche = if count != 0 { element.largest_niche } else { None };
@ -305,7 +305,7 @@ pub fn layout_of_ty_query(
Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields: FieldsShape::Array { stride: element.size, count },
abi,
backend_repr,
largest_niche,
align: element.align,
size,
@ -318,7 +318,7 @@ pub fn layout_of_ty_query(
Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields: FieldsShape::Array { stride: element.size, count: 0 },
abi: Abi::Aggregate { sized: false },
backend_repr: BackendRepr::Memory { sized: false },
largest_niche: None,
align: element.align,
size: Size::ZERO,
@ -329,7 +329,7 @@ pub fn layout_of_ty_query(
TyKind::Str => Layout {
variants: Variants::Single { index: struct_variant_idx() },
fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
abi: Abi::Aggregate { sized: false },
backend_repr: BackendRepr::Memory { sized: false },
largest_niche: None,
align: dl.i8_align,
size: Size::ZERO,
@ -379,8 +379,8 @@ pub fn layout_of_ty_query(
TyKind::Never => cx.calc.layout_of_never_type(),
TyKind::Dyn(_) | TyKind::Foreign(_) => {
let mut unit = layout_of_unit(&cx)?;
match &mut unit.abi {
Abi::Aggregate { sized } => *sized = false,
match &mut unit.backend_repr {
BackendRepr::Memory { sized } => *sized = false,
_ => return Err(LayoutError::Unknown),
}
unit

View file

@ -4102,7 +4102,6 @@ ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
ui/type-alias-impl-trait/issue-57611-trait-alias.rs
ui/type-alias-impl-trait/issue-57700.rs
ui/type-alias-impl-trait/issue-57807-associated-type.rs
ui/type-alias-impl-trait/issue-57961.rs
ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs