Skip to content

Rollup of 6 pull requests #90967

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
extended_asm.add_input_operand(None, "r", result.llval);
extended_asm.add_clobber("memory");
extended_asm.set_volatile_flag(true);

// We have copied the value to `result` already.
return;
}
Expand Down Expand Up @@ -363,10 +363,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
cond
}

fn sideeffect(&mut self) {
// TODO(antoyo)
}

fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Value) -> Self::Value {
// Unsupported.
self.context.new_rvalue_from_int(self.int_type, 0)
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,6 @@ impl CodegenCx<'b, 'tcx> {
ifn!("llvm.trap", fn() -> void);
ifn!("llvm.debugtrap", fn() -> void);
ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
ifn!("llvm.sideeffect", fn() -> void);

ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,15 +392,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)])
}

fn sideeffect(&mut self) {
// This kind of check would make a ton of sense in the caller, but currently the only
// caller of this function is in `rustc_codegen_ssa`, which is agnostic to whether LLVM
// codegen backend being used, and so is unable to check the LLVM version.
if unsafe { llvm::LLVMRustVersionMajor() } < 12 {
self.call_intrinsic("llvm.sideeffect", &[]);
}
}

fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value {
// Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time
// optimization pass replaces calls to this intrinsic with code to test type membership.
Expand Down
11 changes: 0 additions & 11 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -980,17 +980,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}

mir::TerminatorKind::Goto { target } => {
if bb == target {
// This is an unconditional branch back to this same basic block. That means we
// have something like a `loop {}` statement. LLVM versions before 12.0
// miscompile this because they assume forward progress. For older versions
// try to handle just this specific case which comes up commonly in practice
// (e.g., in embedded code).
//
// NB: the `sideeffect` currently checks for the LLVM version used internally.
bx.sideeffect();
}

helper.funclet_br(self, &mut bx, target);
}

Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
fn abort(&mut self);
fn assume(&mut self, val: Self::Value);
fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value;
/// Emits a forced side effect.
///
/// Currently has any effect only when LLVM versions prior to 12.0 are used as the backend.
fn sideeffect(&mut self);
/// Trait method used to test whether a given pointer is associated with a type identifier.
fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value;
/// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_infer/src/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness};
use rustc_span::symbol::Ident;
use rustc_span::Span;

pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -97,6 +98,22 @@ pub fn elaborate_predicates<'tcx>(
elaborate_obligations(tcx, obligations)
}

pub fn elaborate_predicates_with_span<'tcx>(
tcx: TyCtxt<'tcx>,
predicates: impl Iterator<Item = (ty::Predicate<'tcx>, Span)>,
) -> Elaborator<'tcx> {
let obligations = predicates
.map(|(predicate, span)| {
predicate_obligation(
predicate,
ty::ParamEnv::empty(),
ObligationCause::dummy_with_span(span),
)
})
.collect();
elaborate_obligations(tcx, obligations)
}

pub fn elaborate_obligations<'tcx>(
tcx: TyCtxt<'tcx>,
mut obligations: Vec<PredicateObligation<'tcx>>,
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,33 @@ pub(crate) fn emit_unescape_error(
Applicability::MachineApplicable,
);
}
} else {
let printable: Vec<char> = lit
.chars()
.filter(|&x| {
unicode_width::UnicodeWidthChar::width(x).unwrap_or(0) != 0
&& !x.is_whitespace()
})
.collect();

if let [ch] = printable.as_slice() {
has_help = true;

handler.span_note(
span,
&format!(
"there are non-printing characters, the full sequence is `{}`",
lit.escape_default(),
),
);

handler.span_suggestion(
span,
"consider removing the non-printing characters",
ch.to_string(),
Applicability::MaybeIncorrect,
);
}
}

if !has_help {
Expand Down
32 changes: 32 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ impl CheckAttrVisitor<'tcx> {
self.check_default_method_body_is_const(attr, span, target)
}
sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
sym::must_use => self.check_must_use(hir_id, &attr, span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
Expand Down Expand Up @@ -1046,6 +1047,37 @@ impl CheckAttrVisitor<'tcx> {
is_valid
}

/// Warns against some misuses of `#[must_use]`
fn check_must_use(
&self,
hir_id: HirId,
attr: &Attribute,
span: &Span,
_target: Target,
) -> bool {
let node = self.tcx.hir().get(hir_id);
if let Some(fn_node) = node.fn_kind() {
if let rustc_hir::IsAsync::Async = fn_node.asyncness() {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build(
"`must_use` attribute on `async` functions \
applies to the anonymous `Future` returned by the \
function, not the value within",
)
.span_label(
*span,
"this attribute does nothing, the `Future`s \
returned by async functions are already `must_use`",
)
.emit();
});
}
}

// For now, its always valid
true
}

/// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid.
fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError}
pub use self::structural_match::search_for_structural_match_violation;
pub use self::structural_match::NonStructuralMatchTy;
pub use self::util::{
elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs,
elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
elaborate_trait_ref, elaborate_trait_refs,
};
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
pub use self::util::{
Expand Down
25 changes: 22 additions & 3 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1641,19 +1641,38 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) {

/// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
/// aren't true.
fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirId) {
let empty_env = ty::ParamEnv::empty();

let def_id = fcx.tcx.hir().local_def_id(id);
let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p);
let predicates_with_span =
fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, span)| (*p, *span));
// Check elaborated bounds.
let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
let implied_obligations = traits::elaborate_predicates_with_span(fcx.tcx, predicates_with_span);

for obligation in implied_obligations {
let pred = obligation.predicate;
// Match the existing behavior.
if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
let pred = fcx.normalize_associated_types_in(span, pred);
let hir_node = fcx.tcx.hir().find(id);

// only use the span of the predicate clause (#90869)

if let Some(hir::Generics { where_clause, .. }) =
hir_node.and_then(|node| node.generics())
{
let obligation_span = obligation.cause.span(fcx.tcx);

span = where_clause
.predicates
.iter()
// There seems to be no better way to find out which predicate we are in
.find(|pred| pred.span().contains(obligation_span))
.map(|pred| pred.span())
.unwrap_or(obligation_span);
}

let obligation = traits::Obligation::new(
traits::ObligationCause::new(span, id, traits::TrivialBound),
empty_env,
Expand Down
30 changes: 29 additions & 1 deletion library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,34 @@ impl<T, A: Allocator> Vec<T, A> {
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.retain_mut(|elem| f(elem));
}

/// Retains only the elements specified by the predicate, passing a mutable reference to it.
///
/// In other words, remove all elements `e` such that `f(&mut e)` returns `false`.
/// This method operates in place, visiting each element exactly once in the
/// original order, and preserves the order of the retained elements.
///
/// # Examples
///
/// ```
/// #![feature(vec_retain_mut)]
///
/// let mut vec = vec![1, 2, 3, 4];
/// vec.retain_mut(|x| if *x > 3 {
/// false
/// } else {
/// *x += 1;
/// true
/// });
/// assert_eq!(vec, [2, 3, 4]);
/// ```
#[unstable(feature = "vec_retain_mut", issue = "90829")]
pub fn retain_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut T) -> bool,
{
let original_len = self.len();
// Avoid double drop if the drop guard is not executed,
Expand Down Expand Up @@ -1496,7 +1524,7 @@ impl<T, A: Allocator> Vec<T, A> {
g: &mut BackshiftOnDrop<'_, T, A>,
) -> bool
where
F: FnMut(&T) -> bool,
F: FnMut(&mut T) -> bool,
{
// SAFETY: Unchecked element must be valid.
let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) };
Expand Down
12 changes: 6 additions & 6 deletions library/std/src/thread/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ macro_rules! __thread_local_inner {
#[cfg_attr(not(windows), inline)] // see comments below
unsafe fn __getit() -> $crate::option::Option<&'static $t> {
const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local();
const INIT_EXPR: $t = $init;

// wasm without atomics maps directly to `static mut`, and dtors
// aren't implemented because thread dtors aren't really a thing
Expand All @@ -174,7 +175,7 @@ macro_rules! __thread_local_inner {
// block.
#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))]
{
static mut VAL: $t = $init;
static mut VAL: $t = INIT_EXPR;
Some(&VAL)
}

Expand All @@ -184,18 +185,17 @@ macro_rules! __thread_local_inner {
not(all(target_arch = "wasm32", not(target_feature = "atomics"))),
))]
{
#[thread_local]
static mut VAL: $t = INIT_EXPR;

// If a dtor isn't needed we can do something "very raw" and
// just get going.
if !$crate::mem::needs_drop::<$t>() {
#[thread_local]
static mut VAL: $t = $init;
unsafe {
return Some(&VAL)
}
}

#[thread_local]
static mut VAL: $t = $init;
// 0 == dtor not registered
// 1 == dtor registered, dtor not run
// 2 == dtor registered and is running or has run
Expand Down Expand Up @@ -242,7 +242,7 @@ macro_rules! __thread_local_inner {
))]
{
#[inline]
const fn __init() -> $t { $init }
const fn __init() -> $t { INIT_EXPR }
static __KEY: $crate::thread::__OsLocalKeyInner<$t> =
$crate::thread::__OsLocalKeyInner::new();
#[allow(unused_unsafe)]
Expand Down
9 changes: 4 additions & 5 deletions src/test/ui/const-generics/issues/issue-67185-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ trait Bar {}
impl Bar for [u16; 4] {}
impl Bar for [[u16; 3]; 3] {}

trait Foo //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277]
//~^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277]
where
[<u8 as Baz>::Quaks; 2]: Bar,
<u8 as Baz>::Quaks: Bar,
trait Foo
where
[<u8 as Baz>::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277]
<u8 as Baz>::Quaks: Bar, //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277]
{
}

Expand Down
Loading