Auto merge of #115009 - matthiaskrgr:rollup-ainf2gb, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #114605 (Increase clarity about Hash - Eq consistency in HashMap and HashSet docs) - #114934 (instantiate response: no unnecessary new universe) - #114950 (Inline strlen_rt in CStr::from_ptr) - #114973 (Expose core::error::request_value in std) - #114983 (Usage zero as language id for `FormatMessageW()`) - #114991 (remove redundant var rebindings) - #114992 (const-eval: ensure we never const-execute a function marked rustc_do_not_const_check) - #115001 (clippy::perf stuff) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f32ced6481
16 changed files with 213 additions and 69 deletions
|
|
@ -427,52 +427,41 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
|
||||
fn find_mir_or_eval_fn(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
orig_instance: ty::Instance<'tcx>,
|
||||
_abi: CallAbi,
|
||||
args: &[FnArg<'tcx>],
|
||||
dest: &PlaceTy<'tcx>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
_unwind: mir::UnwindAction, // unwinding is not supported in consts
|
||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
debug!("find_mir_or_eval_fn: {:?}", instance);
|
||||
debug!("find_mir_or_eval_fn: {:?}", orig_instance);
|
||||
|
||||
// Replace some functions.
|
||||
let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else {
|
||||
// Call has already been handled.
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Only check non-glue functions
|
||||
if let ty::InstanceDef::Item(def) = instance.def {
|
||||
// Execution might have wandered off into other crates, so we cannot do a stability-
|
||||
// sensitive check here. But we can at least rule out functions that are not const
|
||||
// at all.
|
||||
if !ecx.tcx.is_const_fn_raw(def) {
|
||||
// allow calling functions inside a trait marked with #[const_trait].
|
||||
if !ecx.tcx.is_const_default_method(def) {
|
||||
// We certainly do *not* want to actually call the fn
|
||||
// though, so be sure we return here.
|
||||
throw_unsup_format!("calling non-const function `{}`", instance)
|
||||
}
|
||||
}
|
||||
|
||||
let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
if new_instance != instance {
|
||||
// We call another const fn instead.
|
||||
// However, we return the *original* instance to make backtraces work out
|
||||
// (and we hope this does not confuse the FnAbi checks too much).
|
||||
return Ok(Self::find_mir_or_eval_fn(
|
||||
ecx,
|
||||
new_instance,
|
||||
_abi,
|
||||
args,
|
||||
dest,
|
||||
ret,
|
||||
_unwind,
|
||||
)?
|
||||
.map(|(body, _instance)| (body, instance)));
|
||||
// sensitive check here. But we can at least rule out functions that are not const at
|
||||
// all. That said, we have to allow calling functions inside a trait marked with
|
||||
// #[const_trait]. These *are* const-checked!
|
||||
// FIXME: why does `is_const_fn_raw` not classify them as const?
|
||||
if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def))
|
||||
|| ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
|
||||
{
|
||||
// We certainly do *not* want to actually call the fn
|
||||
// though, so be sure we return here.
|
||||
throw_unsup_format!("calling non-const function `{}`", instance)
|
||||
}
|
||||
}
|
||||
|
||||
// This is a const fn. Call it.
|
||||
Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
|
||||
// In case of replacement, we return the *original* instance to make backtraces work out
|
||||
// (and we hope this does not confuse the FnAbi checks too much).
|
||||
Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
|
||||
}
|
||||
|
||||
fn call_intrinsic(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_span::symbol::kw::{Empty, Underscore};
|
|||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use std::fmt::Write;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub(super) fn lint_dot_call_from_2018(
|
||||
|
|
@ -143,16 +144,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
|
||||
if precise {
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
|
||||
format!(
|
||||
", {}",
|
||||
self.sess().source_map().span_to_snippet(span).unwrap()
|
||||
)
|
||||
})
|
||||
.collect::<String>();
|
||||
let args = args.iter().fold(String::new(), |mut string, arg| {
|
||||
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
|
||||
write!(
|
||||
string,
|
||||
", {}",
|
||||
self.sess().source_map().span_to_snippet(span).unwrap()
|
||||
)
|
||||
.unwrap();
|
||||
string
|
||||
});
|
||||
|
||||
lint.span_suggestion(
|
||||
sp,
|
||||
|
|
|
|||
|
|
@ -164,18 +164,15 @@ pub fn provide(providers: &mut Providers) {
|
|||
tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
|
||||
};
|
||||
providers.def_span = |tcx, def_id| {
|
||||
let def_id = def_id;
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP)
|
||||
};
|
||||
providers.def_ident_span = |tcx, def_id| {
|
||||
let def_id = def_id;
|
||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
tcx.hir().opt_ident_span(hir_id)
|
||||
};
|
||||
providers.fn_arg_names = |tcx, id| {
|
||||
providers.fn_arg_names = |tcx, def_id| {
|
||||
let hir = tcx.hir();
|
||||
let def_id = id;
|
||||
let hir_id = hir.local_def_id_to_hir_id(def_id);
|
||||
if let Some(body_id) = hir.maybe_body_owned_by(def_id) {
|
||||
tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
|
||||
|
|
@ -190,7 +187,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
{
|
||||
idents
|
||||
} else {
|
||||
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
|
||||
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id);
|
||||
}
|
||||
};
|
||||
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! Diagnostics related methods for `Ty`.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use crate::ty::{
|
||||
|
|
@ -335,10 +336,10 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
// - insert: `, X: Bar`
|
||||
suggestions.push((
|
||||
generics.tail_span_for_predicate_suggestion(),
|
||||
constraints
|
||||
.iter()
|
||||
.map(|&(constraint, _)| format!(", {param_name}: {constraint}"))
|
||||
.collect::<String>(),
|
||||
constraints.iter().fold(String::new(), |mut string, &(constraint, _)| {
|
||||
write!(string, ", {param_name}: {constraint}").unwrap();
|
||||
string
|
||||
}),
|
||||
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
|
||||
));
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -199,9 +199,9 @@ impl DebugOptions {
|
|||
|
||||
fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool {
|
||||
if let Some(val) = some_strval {
|
||||
if vec!["yes", "y", "on", "true"].contains(&val) {
|
||||
if ["yes", "y", "on", "true"].contains(&val) {
|
||||
true
|
||||
} else if vec!["no", "n", "off", "false"].contains(&val) {
|
||||
} else if ["no", "n", "off", "false"].contains(&val) {
|
||||
false
|
||||
} else {
|
||||
bug!(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
|
|||
}
|
||||
|
||||
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
||||
let tcx = tcx;
|
||||
let param_env = tcx.param_env(item_def_id);
|
||||
let ty = tcx.type_of(item_def_id).instantiate_identity();
|
||||
match tcx.layout_of(param_env.and(ty)) {
|
||||
|
|
|
|||
|
|
@ -1105,7 +1105,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// Then do a second pass for inputs
|
||||
let mut succ = succ;
|
||||
for (op, _op_sp) in asm.operands.iter().rev() {
|
||||
match op {
|
||||
hir::InlineAsmOperand::In { expr, .. } => {
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||
// created inside of the query directly instead of returning them to the
|
||||
// caller.
|
||||
let prev_universe = self.infcx.universe();
|
||||
let universes_created_in_query = response.max_universe.index() + 1;
|
||||
let universes_created_in_query = response.max_universe.index();
|
||||
for _ in 0..universes_created_in_query {
|
||||
self.infcx.create_next_universe();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ impl CStr {
|
|||
/// ```
|
||||
///
|
||||
/// [valid]: core::ptr#safety
|
||||
#[inline]
|
||||
#[inline] // inline is necessary for codegen to see strlen.
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
|
||||
|
|
@ -280,6 +280,8 @@ impl CStr {
|
|||
len
|
||||
}
|
||||
|
||||
// `inline` is necessary for codegen to see strlen.
|
||||
#[inline]
|
||||
fn strlen_rt(s: *const c_char) -> usize {
|
||||
extern "C" {
|
||||
/// Provided by libc or compiler_builtins.
|
||||
|
|
|
|||
|
|
@ -49,12 +49,14 @@ use crate::sys;
|
|||
/// ```
|
||||
///
|
||||
/// In other words, if two keys are equal, their hashes must be equal.
|
||||
/// Violating this property is a logic error.
|
||||
///
|
||||
/// It is a logic error for a key to be modified in such a way that the key's
|
||||
/// It is also a logic error for a key to be modified in such a way that the key's
|
||||
/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
|
||||
/// the [`Eq`] trait, changes while it is in the map. This is normally only
|
||||
/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
|
||||
/// The behavior resulting from such a logic error is not specified, but will
|
||||
///
|
||||
/// The behavior resulting from either logic error is not specified, but will
|
||||
/// be encapsulated to the `HashMap` that observed the logic error and not
|
||||
/// result in undefined behavior. This could include panics, incorrect results,
|
||||
/// aborts, memory leaks, and non-termination.
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@ use super::map::{map_try_reserve_error, RandomState};
|
|||
/// ```
|
||||
///
|
||||
/// In other words, if two keys are equal, their hashes must be equal.
|
||||
/// Violating this property is a logic error.
|
||||
///
|
||||
///
|
||||
/// It is a logic error for a key to be modified in such a way that the key's
|
||||
/// It is also a logic error for a key to be modified in such a way that the key's
|
||||
/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
|
||||
/// the [`Eq`] trait, changes while it is in the map. This is normally only
|
||||
/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
|
||||
/// The behavior resulting from such a logic error is not specified, but will
|
||||
///
|
||||
/// The behavior resulting from either logic error is not specified, but will
|
||||
/// be encapsulated to the `HashSet` that observed the logic error and not
|
||||
/// result in undefined behavior. This could include panics, incorrect results,
|
||||
/// aborts, memory leaks, and non-termination.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::fmt::{self, Write};
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::error::Error;
|
||||
#[unstable(feature = "error_generic_member_access", issue = "99301")]
|
||||
pub use core::error::{request_ref, Request};
|
||||
pub use core::error::{request_ref, request_value, Request};
|
||||
|
||||
mod private {
|
||||
// This is a hack to prevent `type_id` from being overridden by `Error`
|
||||
|
|
|
|||
|
|
@ -25,10 +25,6 @@ pub fn errno() -> i32 {
|
|||
|
||||
/// Gets a detailed string description for the given error number.
|
||||
pub fn error_string(mut errnum: i32) -> String {
|
||||
// This value is calculated from the macro
|
||||
// MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
|
||||
let langId = 0x0800 as c::DWORD;
|
||||
|
||||
let mut buf = [0 as c::WCHAR; 2048];
|
||||
|
||||
unsafe {
|
||||
|
|
@ -56,13 +52,13 @@ pub fn error_string(mut errnum: i32) -> String {
|
|||
flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
module,
|
||||
errnum as c::DWORD,
|
||||
langId,
|
||||
0,
|
||||
buf.as_mut_ptr(),
|
||||
buf.len() as c::DWORD,
|
||||
ptr::null(),
|
||||
) as usize;
|
||||
if res == 0 {
|
||||
// Sometimes FormatMessageW can fail e.g., system doesn't like langId,
|
||||
// Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId,
|
||||
let fm_err = errno();
|
||||
return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
// compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
|
||||
// A minimization of an ambiguity when using typenum. See
|
||||
// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55
|
||||
// for more details.
|
||||
trait Id {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
impl<T: ?Sized> Id for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
trait WithAssoc<T: ?Sized> {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
|
||||
|
||||
struct Leaf;
|
||||
struct Wrapper<U: ?Sized>(U);
|
||||
|
||||
impl<U: ?Sized> WithAssoc<U> for Leaf {
|
||||
type Assoc = U;
|
||||
}
|
||||
|
||||
impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
|
||||
where
|
||||
Ul: WithAssoc<Ur>,
|
||||
{
|
||||
type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
|
||||
}
|
||||
|
||||
fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
|
||||
where
|
||||
T: WithAssoc<U, Assoc = V>,
|
||||
{
|
||||
}
|
||||
|
||||
// normalize self type to `Wrapper<Leaf>`
|
||||
// This succeeds, HOWEVER, instantiating the query response previously
|
||||
// incremented the universe index counter.
|
||||
// equate impl headers:
|
||||
// <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
|
||||
// <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
|
||||
// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
|
||||
// add where bounds:
|
||||
// ~> Leaf: WithAssoc<?3t>
|
||||
// equate with assoc type:
|
||||
// ?0t
|
||||
// <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
|
||||
// ~> AliasRelate(
|
||||
// <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
|
||||
// Equate,
|
||||
// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
|
||||
// )
|
||||
//
|
||||
// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
|
||||
// it after incrementing the universe index while normalizing the self type.
|
||||
//
|
||||
// evaluate_added_goals_and_make_query_response:
|
||||
// AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
|
||||
// YES, constrains ?3t to Leaf
|
||||
// AliasRelate(
|
||||
// <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
|
||||
// Equate,
|
||||
// <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
|
||||
// )
|
||||
//
|
||||
// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
|
||||
// results in ambiguity.
|
||||
fn main() {
|
||||
bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// compile-flags: -Ztrait-solver=next
|
||||
// known-bug: trait-system-refactor-initiative#60
|
||||
|
||||
// Generalizing a projection containing an inference variable
|
||||
// which cannot be named by the `root_vid` can result in ambiguity.
|
||||
//
|
||||
// Because we do not decrement the universe index when exiting a forall,
|
||||
// this can cause unexpected failures.
|
||||
//
|
||||
// See generalize-proj-new-universe-index-1.rs for more details.
|
||||
|
||||
// For this reproduction we need:
|
||||
// - an inference variable with a lower universe
|
||||
// - enter a binder to increment the current universe
|
||||
// - create a new inference variable which is constrained by proving a goal
|
||||
// - equate a projection containing the new variable with the first variable
|
||||
// - generalization creates yet another inference variable which is then
|
||||
// part of an alias-relate, resulting this to fail with ambiguity.
|
||||
//
|
||||
// Because we need to enter the binder in-between the creation of the first
|
||||
// and second inference variable, this is easiest via
|
||||
// `assemble_candidates_after_normalizing_self_ty` because eagerly call
|
||||
// `try_evaluate_added_goals` there before creating the inference variables
|
||||
// for the impl parameters.
|
||||
trait Id {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
impl<T: ?Sized> Id for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
// By adding an higher ranked bound to the impl we currently
|
||||
// propagate this bound to the caller, forcing us to create a new
|
||||
// universe.
|
||||
trait IdHigherRankedBound {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
|
||||
impl<T: ?Sized> IdHigherRankedBound for T
|
||||
where
|
||||
for<'a> T: 'a,
|
||||
{
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
trait WithAssoc<T: ?Sized> {
|
||||
type Assoc: ?Sized;
|
||||
}
|
||||
|
||||
|
||||
struct Leaf;
|
||||
struct Wrapper<U: ?Sized>(U);
|
||||
struct Rigid;
|
||||
|
||||
impl<U: ?Sized> WithAssoc<U> for Leaf {
|
||||
type Assoc = U;
|
||||
}
|
||||
|
||||
|
||||
impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
|
||||
where
|
||||
Leaf: WithAssoc<Ur>,
|
||||
{
|
||||
type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
|
||||
}
|
||||
|
||||
fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
|
||||
where
|
||||
T: WithAssoc<U, Assoc = V>,
|
||||
{
|
||||
}
|
||||
|
||||
fn main() {
|
||||
bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
error[E0282]: type annotations needed
|
||||
--> $DIR/generalize-proj-new-universe-index-2.rs:74:5
|
||||
|
|
||||
LL | bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue