Auto merge of #137608 - fmease:rollup-h4siso6, r=fmease
Rollup of 8 pull requests Successful merges: - #137370 (adjust_abi: make fallback logic for ABIs a bit easier to read) - #137444 (Improve behavior of `IF_LET_RESCOPE` around temporaries and place expressions) - #137464 (Fix invalid suggestion from type error for derive macro) - #137539 ( Add rustdoc-gui regression test for #137082 ) - #137576 (Don't doc-comment BTreeMap<K, SetValZST, A>) - #137595 (remove `simd_fpow` and `simd_fpowi`) - #137600 (type_ir: remove redundant part of comment) - #137602 (feature: fix typo in attribute description) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
85abb27636
26 changed files with 251 additions and 391 deletions
|
@ -460,64 +460,6 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::simd_fpow => {
|
|
||||||
intrinsic_args!(fx, args => (a, b); intrinsic);
|
|
||||||
|
|
||||||
if !a.layout().ty.is_simd() {
|
|
||||||
report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
simd_pair_for_each_lane(fx, a, b, ret, &|fx, lane_ty, _ret_lane_ty, a_lane, b_lane| {
|
|
||||||
match lane_ty.kind() {
|
|
||||||
ty::Float(FloatTy::F32) => fx.lib_call(
|
|
||||||
"powf",
|
|
||||||
vec![AbiParam::new(types::F32), AbiParam::new(types::F32)],
|
|
||||||
vec![AbiParam::new(types::F32)],
|
|
||||||
&[a_lane, b_lane],
|
|
||||||
)[0],
|
|
||||||
ty::Float(FloatTy::F64) => fx.lib_call(
|
|
||||||
"pow",
|
|
||||||
vec![AbiParam::new(types::F64), AbiParam::new(types::F64)],
|
|
||||||
vec![AbiParam::new(types::F64)],
|
|
||||||
&[a_lane, b_lane],
|
|
||||||
)[0],
|
|
||||||
_ => unreachable!("{:?}", lane_ty),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sym::simd_fpowi => {
|
|
||||||
intrinsic_args!(fx, args => (a, exp); intrinsic);
|
|
||||||
let exp = exp.load_scalar(fx);
|
|
||||||
|
|
||||||
if !a.layout().ty.is_simd() {
|
|
||||||
report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
simd_for_each_lane(
|
|
||||||
fx,
|
|
||||||
a,
|
|
||||||
ret,
|
|
||||||
&|fx, lane_ty, _ret_lane_ty, lane| match lane_ty.kind() {
|
|
||||||
ty::Float(FloatTy::F32) => fx.lib_call(
|
|
||||||
"__powisf2", // compiler-builtins
|
|
||||||
vec![AbiParam::new(types::F32), AbiParam::new(types::I32)],
|
|
||||||
vec![AbiParam::new(types::F32)],
|
|
||||||
&[lane, exp],
|
|
||||||
)[0],
|
|
||||||
ty::Float(FloatTy::F64) => fx.lib_call(
|
|
||||||
"__powidf2", // compiler-builtins
|
|
||||||
vec![AbiParam::new(types::F64), AbiParam::new(types::I32)],
|
|
||||||
vec![AbiParam::new(types::F64)],
|
|
||||||
&[lane, exp],
|
|
||||||
)[0],
|
|
||||||
_ => unreachable!("{:?}", lane_ty),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sym::simd_fsin
|
sym::simd_fsin
|
||||||
| sym::simd_fcos
|
| sym::simd_fcos
|
||||||
| sym::simd_fexp
|
| sym::simd_fexp
|
||||||
|
|
|
@ -772,8 +772,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||||
sym::simd_floor => "floor",
|
sym::simd_floor => "floor",
|
||||||
sym::simd_fma => "fma",
|
sym::simd_fma => "fma",
|
||||||
sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary
|
sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary
|
||||||
sym::simd_fpowi => "__builtin_powi",
|
|
||||||
sym::simd_fpow => "pow",
|
|
||||||
sym::simd_fsin => "sin",
|
sym::simd_fsin => "sin",
|
||||||
sym::simd_fsqrt => "sqrt",
|
sym::simd_fsqrt => "sqrt",
|
||||||
sym::simd_round => "round",
|
sym::simd_round => "round",
|
||||||
|
@ -788,14 +786,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||||
let mut vector_elements = vec![];
|
let mut vector_elements = vec![];
|
||||||
for i in 0..in_len {
|
for i in 0..in_len {
|
||||||
let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64);
|
let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64);
|
||||||
// we have to treat fpowi specially, since fpowi's second argument is always an i32
|
|
||||||
let mut arguments = vec![];
|
let mut arguments = vec![];
|
||||||
if name == sym::simd_fpowi {
|
|
||||||
arguments = vec![
|
|
||||||
bx.extract_element(args[0].immediate(), index).to_rvalue(),
|
|
||||||
args[1].immediate(),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
|
let mut element = bx.extract_element(arg.immediate(), index).to_rvalue();
|
||||||
// FIXME: it would probably be better to not have casts here and use the proper
|
// FIXME: it would probably be better to not have casts here and use the proper
|
||||||
|
@ -805,7 +796,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||||
}
|
}
|
||||||
arguments.push(element);
|
arguments.push(element);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
let mut result = bx.context.new_call(None, function, &arguments);
|
let mut result = bx.context.new_call(None, function, &arguments);
|
||||||
if cast_type.is_some() {
|
if cast_type.is_some() {
|
||||||
result = bx.context.new_cast(None, result, elem_ty);
|
result = bx.context.new_cast(None, result, elem_ty);
|
||||||
|
@ -829,8 +819,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
||||||
| sym::simd_floor
|
| sym::simd_floor
|
||||||
| sym::simd_fma
|
| sym::simd_fma
|
||||||
| sym::simd_relaxed_fma
|
| sym::simd_relaxed_fma
|
||||||
| sym::simd_fpow
|
|
||||||
| sym::simd_fpowi
|
|
||||||
| sym::simd_fsin
|
| sym::simd_fsin
|
||||||
| sym::simd_fsqrt
|
| sym::simd_fsqrt
|
||||||
| sym::simd_round
|
| sym::simd_round
|
||||||
|
|
|
@ -1581,8 +1581,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||||
sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
|
sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
|
sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
|
||||||
sym::simd_relaxed_fma => ("fmuladd", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
|
sym::simd_relaxed_fma => ("fmuladd", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)),
|
||||||
sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)),
|
|
||||||
sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)),
|
|
||||||
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
|
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
|
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
|
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
@ -1615,8 +1613,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||||
| sym::simd_flog
|
| sym::simd_flog
|
||||||
| sym::simd_floor
|
| sym::simd_floor
|
||||||
| sym::simd_fma
|
| sym::simd_fma
|
||||||
| sym::simd_fpow
|
|
||||||
| sym::simd_fpowi
|
|
||||||
| sym::simd_fsin
|
| sym::simd_fsin
|
||||||
| sym::simd_fsqrt
|
| sym::simd_fsqrt
|
||||||
| sym::simd_relaxed_fma
|
| sym::simd_relaxed_fma
|
||||||
|
|
|
@ -1011,7 +1011,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
),
|
),
|
||||||
rustc_attr!(
|
rustc_attr!(
|
||||||
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
|
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
|
||||||
"#![rustc_force_inline] forces a free function to be inlined"
|
"#[rustc_force_inline] forces a free function to be inlined"
|
||||||
),
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
|
@ -645,7 +645,6 @@ pub fn check_intrinsic_type(
|
||||||
| sym::simd_xor
|
| sym::simd_xor
|
||||||
| sym::simd_fmin
|
| sym::simd_fmin
|
||||||
| sym::simd_fmax
|
| sym::simd_fmax
|
||||||
| sym::simd_fpow
|
|
||||||
| sym::simd_saturating_add
|
| sym::simd_saturating_add
|
||||||
| sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
|
| sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
|
||||||
sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)),
|
sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)),
|
||||||
|
@ -668,7 +667,6 @@ pub fn check_intrinsic_type(
|
||||||
| sym::simd_floor
|
| sym::simd_floor
|
||||||
| sym::simd_round
|
| sym::simd_round
|
||||||
| sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
|
| sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
|
||||||
sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)),
|
|
||||||
sym::simd_fma | sym::simd_relaxed_fma => {
|
sym::simd_fma | sym::simd_relaxed_fma => {
|
||||||
(1, 0, vec![param(0), param(0), param(0)], param(0))
|
(1, 0, vec![param(0), param(0), param(0)], param(0))
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ use rustc_middle::ty::{
|
||||||
};
|
};
|
||||||
use rustc_session::errors::ExprParenthesesNeeded;
|
use rustc_session::errors::ExprParenthesesNeeded;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::{Ident, Span, Symbol, sym};
|
use rustc_span::{ExpnKind, Ident, MacroKind, Span, Symbol, sym};
|
||||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||||
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
|
use rustc_trait_selection::error_reporting::traits::DefIdOrName;
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
|
@ -1365,6 +1365,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.param_env,
|
self.param_env,
|
||||||
ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
|
ty::TraitRef::new(self.tcx, into_def_id, [expr_ty, expected_ty]),
|
||||||
))
|
))
|
||||||
|
&& !expr
|
||||||
|
.span
|
||||||
|
.macro_backtrace()
|
||||||
|
.any(|x| matches!(x.kind, ExpnKind::Macro(MacroKind::Attr | MacroKind::Derive, ..)))
|
||||||
{
|
{
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use hir::intravisit::Visitor;
|
use hir::intravisit::{self, Visitor};
|
||||||
use rustc_ast::Recovered;
|
use rustc_ast::Recovered;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
|
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
|
||||||
|
@ -9,6 +9,7 @@ use rustc_errors::{
|
||||||
use rustc_hir::{self as hir, HirIdSet};
|
use rustc_hir::{self as hir, HirIdSet};
|
||||||
use rustc_macros::LintDiagnostic;
|
use rustc_macros::LintDiagnostic;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
|
use rustc_middle::ty::adjustment::Adjust;
|
||||||
use rustc_session::lint::{FutureIncompatibilityReason, LintId};
|
use rustc_session::lint::{FutureIncompatibilityReason, LintId};
|
||||||
use rustc_session::{declare_lint, impl_lint_pass};
|
use rustc_session::{declare_lint, impl_lint_pass};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -160,7 +161,7 @@ impl IfLetRescope {
|
||||||
let lifetime_end = source_map.end_point(conseq.span);
|
let lifetime_end = source_map.end_point(conseq.span);
|
||||||
|
|
||||||
if let ControlFlow::Break(significant_dropper) =
|
if let ControlFlow::Break(significant_dropper) =
|
||||||
(FindSignificantDropper { cx }).visit_expr(init)
|
(FindSignificantDropper { cx }).check_if_let_scrutinee(init)
|
||||||
{
|
{
|
||||||
first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id)));
|
first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id)));
|
||||||
significant_droppers.push(significant_dropper);
|
significant_droppers.push(significant_dropper);
|
||||||
|
@ -363,96 +364,97 @@ enum SingleArmMatchBegin {
|
||||||
WithoutOpenBracket(Span),
|
WithoutOpenBracket(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FindSignificantDropper<'tcx, 'a> {
|
struct FindSignificantDropper<'a, 'tcx> {
|
||||||
cx: &'a LateContext<'tcx>,
|
cx: &'a LateContext<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
|
impl<'tcx> FindSignificantDropper<'_, 'tcx> {
|
||||||
type Result = ControlFlow<Span>;
|
/// Check the scrutinee of an `if let` to see if it promotes any temporary values
|
||||||
|
/// that would change drop order in edition 2024. Specifically, it checks the value
|
||||||
|
/// of the scrutinee itself, and also recurses into the expression to find any ref
|
||||||
|
/// exprs (or autoref) which would promote temporaries that would be scoped to the
|
||||||
|
/// end of this `if`.
|
||||||
|
fn check_if_let_scrutinee(&mut self, init: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
|
||||||
|
self.check_promoted_temp_with_drop(init)?;
|
||||||
|
self.visit_expr(init)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
|
/// Check that an expression is not a promoted temporary with a significant
|
||||||
if self
|
/// drop impl.
|
||||||
|
///
|
||||||
|
/// An expression is a promoted temporary if it has an addr taken (i.e. `&expr` or autoref)
|
||||||
|
/// or is the scrutinee of the `if let`, *and* the expression is not a place
|
||||||
|
/// expr, and it has a significant drop.
|
||||||
|
fn check_promoted_temp_with_drop(&self, expr: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
|
||||||
|
if !expr.is_place_expr(|base| {
|
||||||
|
self.cx
|
||||||
|
.typeck_results()
|
||||||
|
.adjustments()
|
||||||
|
.get(base.hir_id)
|
||||||
|
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
|
||||||
|
}) && self
|
||||||
.cx
|
.cx
|
||||||
.typeck_results()
|
.typeck_results()
|
||||||
.expr_ty(expr)
|
.expr_ty(expr)
|
||||||
.has_significant_drop(self.cx.tcx, self.cx.typing_env())
|
.has_significant_drop(self.cx.tcx, self.cx.typing_env())
|
||||||
{
|
{
|
||||||
return ControlFlow::Break(expr.span);
|
ControlFlow::Break(expr.span)
|
||||||
|
} else {
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Visitor<'tcx> for FindSignificantDropper<'_, 'tcx> {
|
||||||
|
type Result = ControlFlow<Span>;
|
||||||
|
|
||||||
|
fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) -> Self::Result {
|
||||||
|
// Blocks introduce temporary terminating scope for all of its
|
||||||
|
// statements, so just visit the tail expr, skipping over any
|
||||||
|
// statements. This prevents false positives like `{ let x = &Drop; }`.
|
||||||
|
if let Some(expr) = b.expr { self.visit_expr(expr) } else { ControlFlow::Continue(()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
|
||||||
|
// Check for promoted temporaries from autoref, e.g.
|
||||||
|
// `if let None = TypeWithDrop.as_ref() {} else {}`
|
||||||
|
// where `fn as_ref(&self) -> Option<...>`.
|
||||||
|
for adj in self.cx.typeck_results().expr_adjustments(expr) {
|
||||||
|
match adj.kind {
|
||||||
|
// Skip when we hit the first deref expr.
|
||||||
|
Adjust::Deref(_) => break,
|
||||||
|
Adjust::Borrow(_) => {
|
||||||
|
self.check_promoted_temp_with_drop(expr)?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::ConstBlock(_)
|
// Account for cases like `if let None = Some(&Drop) {} else {}`.
|
||||||
| hir::ExprKind::Lit(_)
|
hir::ExprKind::AddrOf(_, _, expr) => {
|
||||||
| hir::ExprKind::Path(_)
|
self.check_promoted_temp_with_drop(expr)?;
|
||||||
| hir::ExprKind::Assign(_, _, _)
|
intravisit::walk_expr(self, expr)
|
||||||
| hir::ExprKind::AssignOp(_, _, _)
|
|
||||||
| hir::ExprKind::Break(_, _)
|
|
||||||
| hir::ExprKind::Continue(_)
|
|
||||||
| hir::ExprKind::Ret(_)
|
|
||||||
| hir::ExprKind::Become(_)
|
|
||||||
| hir::ExprKind::InlineAsm(_)
|
|
||||||
| hir::ExprKind::OffsetOf(_, _)
|
|
||||||
| hir::ExprKind::Repeat(_, _)
|
|
||||||
| hir::ExprKind::Err(_)
|
|
||||||
| hir::ExprKind::Struct(_, _, _)
|
|
||||||
| hir::ExprKind::Closure(_)
|
|
||||||
| hir::ExprKind::Block(_, _)
|
|
||||||
| hir::ExprKind::DropTemps(_)
|
|
||||||
| hir::ExprKind::Loop(_, _, _, _) => ControlFlow::Continue(()),
|
|
||||||
|
|
||||||
hir::ExprKind::Tup(exprs) | hir::ExprKind::Array(exprs) => {
|
|
||||||
for expr in exprs {
|
|
||||||
self.visit_expr(expr)?;
|
|
||||||
}
|
}
|
||||||
ControlFlow::Continue(())
|
// `(Drop, ()).1` introduces a temporary and then moves out of
|
||||||
}
|
// part of it, therefore we should check it for temporaries.
|
||||||
hir::ExprKind::Call(callee, args) => {
|
// FIXME: This may have false positives if we move the part
|
||||||
self.visit_expr(callee)?;
|
// that actually has drop, but oh well.
|
||||||
for expr in args {
|
hir::ExprKind::Index(expr, _, _) | hir::ExprKind::Field(expr, _) => {
|
||||||
self.visit_expr(expr)?;
|
self.check_promoted_temp_with_drop(expr)?;
|
||||||
}
|
intravisit::walk_expr(self, expr)
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
|
||||||
hir::ExprKind::MethodCall(_, receiver, args, _) => {
|
|
||||||
self.visit_expr(receiver)?;
|
|
||||||
for expr in args {
|
|
||||||
self.visit_expr(expr)?;
|
|
||||||
}
|
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
|
||||||
hir::ExprKind::Index(left, right, _) | hir::ExprKind::Binary(_, left, right) => {
|
|
||||||
self.visit_expr(left)?;
|
|
||||||
self.visit_expr(right)
|
|
||||||
}
|
|
||||||
hir::ExprKind::Unary(_, expr)
|
|
||||||
| hir::ExprKind::Cast(expr, _)
|
|
||||||
| hir::ExprKind::Type(expr, _)
|
|
||||||
| hir::ExprKind::UnsafeBinderCast(_, expr, _)
|
|
||||||
| hir::ExprKind::Yield(expr, _)
|
|
||||||
| hir::ExprKind::AddrOf(_, _, expr)
|
|
||||||
| hir::ExprKind::Match(expr, _, _)
|
|
||||||
| hir::ExprKind::Field(expr, _)
|
|
||||||
| hir::ExprKind::Let(&hir::LetExpr {
|
|
||||||
init: expr,
|
|
||||||
span: _,
|
|
||||||
pat: _,
|
|
||||||
ty: _,
|
|
||||||
recovered: Recovered::No,
|
|
||||||
}) => self.visit_expr(expr),
|
|
||||||
hir::ExprKind::Let(_) => ControlFlow::Continue(()),
|
|
||||||
|
|
||||||
hir::ExprKind::If(cond, _, _) => {
|
|
||||||
if let hir::ExprKind::Let(hir::LetExpr {
|
|
||||||
init,
|
|
||||||
span: _,
|
|
||||||
pat: _,
|
|
||||||
ty: _,
|
|
||||||
recovered: Recovered::No,
|
|
||||||
}) = cond.kind
|
|
||||||
{
|
|
||||||
self.visit_expr(init)?;
|
|
||||||
}
|
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
}
|
||||||
|
// If always introduces a temporary terminating scope for its cond and arms,
|
||||||
|
// so don't visit them.
|
||||||
|
hir::ExprKind::If(..) => ControlFlow::Continue(()),
|
||||||
|
// Match introduces temporary terminating scopes for arms, so don't visit
|
||||||
|
// them, and only visit the scrutinee to account for cases like:
|
||||||
|
// `if let None = match &Drop { _ => Some(1) } {} else {}`.
|
||||||
|
hir::ExprKind::Match(scrut, _, _) => self.visit_expr(scrut),
|
||||||
|
// Self explanatory.
|
||||||
|
hir::ExprKind::DropTemps(_) => ControlFlow::Continue(()),
|
||||||
|
// Otherwise, walk into the expr's parts.
|
||||||
|
_ => intravisit::walk_expr(self, expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1877,8 +1877,6 @@ symbols! {
|
||||||
simd_fma,
|
simd_fma,
|
||||||
simd_fmax,
|
simd_fmax,
|
||||||
simd_fmin,
|
simd_fmin,
|
||||||
simd_fpow,
|
|
||||||
simd_fpowi,
|
|
||||||
simd_fsin,
|
simd_fsin,
|
||||||
simd_fsqrt,
|
simd_fsqrt,
|
||||||
simd_gather,
|
simd_gather,
|
||||||
|
|
|
@ -2914,20 +2914,35 @@ impl Target {
|
||||||
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
|
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
|
||||||
// `__stdcall` only applies on x86 and on non-variadic functions:
|
// `__stdcall` only applies on x86 and on non-variadic functions:
|
||||||
// https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
|
// https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
|
||||||
System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
|
System { unwind } => {
|
||||||
|
if self.is_like_windows && self.arch == "x86" && !c_variadic {
|
||||||
Stdcall { unwind }
|
Stdcall { unwind }
|
||||||
|
} else {
|
||||||
|
C { unwind }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EfiApi => {
|
||||||
|
if self.arch == "arm" {
|
||||||
|
Aapcs { unwind: false }
|
||||||
|
} else if self.arch == "x86_64" {
|
||||||
|
Win64 { unwind: false }
|
||||||
|
} else {
|
||||||
|
C { unwind: false }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
System { unwind } => C { unwind },
|
|
||||||
EfiApi if self.arch == "arm" => Aapcs { unwind: false },
|
|
||||||
EfiApi if self.arch == "x86_64" => Win64 { unwind: false },
|
|
||||||
EfiApi => C { unwind: false },
|
|
||||||
|
|
||||||
// See commentary in `is_abi_supported`.
|
// See commentary in `is_abi_supported`.
|
||||||
Stdcall { .. } | Thiscall { .. } if self.arch == "x86" => abi,
|
Stdcall { unwind } | Thiscall { unwind } | Fastcall { unwind } => {
|
||||||
Stdcall { unwind } | Thiscall { unwind } => C { unwind },
|
if self.arch == "x86" { abi } else { C { unwind } }
|
||||||
Fastcall { .. } if self.arch == "x86" => abi,
|
}
|
||||||
Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
|
Vectorcall { unwind } => {
|
||||||
Fastcall { unwind } | Vectorcall { unwind } => C { unwind },
|
if ["x86", "x86_64"].contains(&&*self.arch) {
|
||||||
|
abi
|
||||||
|
} else {
|
||||||
|
C { unwind }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The Windows x64 calling convention we use for `extern "Rust"`
|
// The Windows x64 calling convention we use for `extern "Rust"`
|
||||||
// <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>
|
// <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>
|
||||||
|
|
|
@ -131,8 +131,6 @@ pub struct TraitPredicate<I: Interner> {
|
||||||
/// If polarity is Negative: we are proving that a negative impl of this trait
|
/// If polarity is Negative: we are proving that a negative impl of this trait
|
||||||
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
||||||
/// exist via a series of predicates.)
|
/// exist via a series of predicates.)
|
||||||
///
|
|
||||||
/// If polarity is Reserved: that's a bug.
|
|
||||||
pub polarity: PredicatePolarity,
|
pub polarity: PredicatePolarity,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,7 @@ impl<K: Clone, V: Clone, A: Allocator + Clone> Clone for BTreeMap<K, V, A> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal functionality for `BTreeSet`.
|
// Internal functionality for `BTreeSet`.
|
||||||
impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
|
impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
|
||||||
pub(super) fn replace(&mut self, key: K) -> Option<K>
|
pub(super) fn replace(&mut self, key: K) -> Option<K>
|
||||||
where
|
where
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.20.2
|
0.20.3
|
|
@ -1,87 +0,0 @@
|
||||||
//@ compile-flags: -C no-prepopulate-passes
|
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
|
||||||
|
|
||||||
#![feature(repr_simd, intrinsics)]
|
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x2(pub [f32; 2]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x4(pub [f32; 4]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x8(pub [f32; 8]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x16(pub [f32; 16]);
|
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
fn simd_fpow<T>(x: T, b: T) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_32x2
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_32x2(a: f32x2, b: f32x2) -> f32x2 {
|
|
||||||
// CHECK: call <2 x float> @llvm.pow.v2f32
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_32x4
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_32x4(a: f32x4, b: f32x4) -> f32x4 {
|
|
||||||
// CHECK: call <4 x float> @llvm.pow.v4f32
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_32x8
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_32x8(a: f32x8, b: f32x8) -> f32x8 {
|
|
||||||
// CHECK: call <8 x float> @llvm.pow.v8f32
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_32x16
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 {
|
|
||||||
// CHECK: call <16 x float> @llvm.pow.v16f32
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f64x2(pub [f64; 2]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f64x4(pub [f64; 4]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f64x8(pub [f64; 8]);
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_64x4
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_64x4(a: f64x4, b: f64x4) -> f64x4 {
|
|
||||||
// CHECK: call <4 x double> @llvm.pow.v4f64
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_64x2
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_64x2(a: f64x2, b: f64x2) -> f64x2 {
|
|
||||||
// CHECK: call <2 x double> @llvm.pow.v2f64
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpow_64x8
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpow_64x8(a: f64x8, b: f64x8) -> f64x8 {
|
|
||||||
// CHECK: call <8 x double> @llvm.pow.v8f64
|
|
||||||
simd_fpow(a, b)
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
//@ compile-flags: -C no-prepopulate-passes
|
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
|
||||||
|
|
||||||
#![feature(repr_simd, intrinsics)]
|
|
||||||
#![allow(non_camel_case_types)]
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x2(pub [f32; 2]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x4(pub [f32; 4]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x8(pub [f32; 8]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f32x16(pub [f32; 16]);
|
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
fn simd_fpowi<T>(x: T, b: i32) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_32x2
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_32x2(a: f32x2, b: i32) -> f32x2 {
|
|
||||||
// CHECK: call <2 x float> @llvm.powi.v2f32
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_32x4
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_32x4(a: f32x4, b: i32) -> f32x4 {
|
|
||||||
// CHECK: call <4 x float> @llvm.powi.v4f32
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_32x8
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_32x8(a: f32x8, b: i32) -> f32x8 {
|
|
||||||
// CHECK: call <8 x float> @llvm.powi.v8f32
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_32x16
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 {
|
|
||||||
// CHECK: call <16 x float> @llvm.powi.v16f32
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f64x2(pub [f64; 2]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f64x4(pub [f64; 4]);
|
|
||||||
|
|
||||||
#[repr(simd)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
||||||
pub struct f64x8(pub [f64; 8]);
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_64x4
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_64x4(a: f64x4, b: i32) -> f64x4 {
|
|
||||||
// CHECK: call <4 x double> @llvm.powi.v4f64
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_64x2
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_64x2(a: f64x2, b: i32) -> f64x2 {
|
|
||||||
// CHECK: call <2 x double> @llvm.powi.v2f64
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @fpowi_64x8
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe fn fpowi_64x8(a: f64x8, b: i32) -> f64x8 {
|
|
||||||
// CHECK: call <8 x double> @llvm.powi.v8f64
|
|
||||||
simd_fpowi(a, b)
|
|
||||||
}
|
|
|
@ -26,6 +26,8 @@ click: ".example-wrap .copy-button"
|
||||||
move-cursor-to: ".search-input"
|
move-cursor-to: ".search-input"
|
||||||
assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0)
|
assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0)
|
||||||
assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
|
assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
|
||||||
|
// Since we clicked on the copy button, the clipboard content should have been updated.
|
||||||
|
assert-clipboard: 'println!("nothing fancy");\nprintln!("but with two lines!");'
|
||||||
|
|
||||||
define-function: (
|
define-function: (
|
||||||
"check-buttons",
|
"check-buttons",
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
// Checks that the "copy path" button is not triggering JS error and its display
|
// Checks that the "copy path" button is not triggering JS error and its display
|
||||||
// isn't broken.
|
// isn't broken and the copied path is as expected.
|
||||||
go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
|
go-to: "file://" + |DOC_PATH| + "/test_docs/foreign_impl_order/trait.Foo.html"
|
||||||
|
|
||||||
|
// We ensure that the clipboard is empty.
|
||||||
|
assert-clipboard: ""
|
||||||
|
|
||||||
// First we store the size of the button before we click on it.
|
// First we store the size of the button before we click on it.
|
||||||
store-size: ("#copy-path", {"width": width, "height": height})
|
store-size: ("#copy-path", {"width": width, "height": height})
|
||||||
click: "#copy-path"
|
click: "#copy-path"
|
||||||
// We wait for the new text to appear.
|
// We wait for the new text to appear.
|
||||||
wait-for: "#copy-path.clicked"
|
wait-for: "#copy-path.clicked"
|
||||||
|
// We check that the clipboard value is the expected one.
|
||||||
|
assert-clipboard: "test_docs::foreign_impl_order::Foo"
|
||||||
// We check that the size didn't change.
|
// We check that the size didn't change.
|
||||||
assert-size: ("#copy-path.clicked", {"width": |width|, "height": |height|})
|
assert-size: ("#copy-path.clicked", {"width": |width|, "height": |height|})
|
||||||
// We wait for the button to turn back to its original state.
|
// We wait for the button to turn back to its original state.
|
||||||
|
|
33
tests/ui/drop/lint-if-let-rescope-false-positives.rs
Normal file
33
tests/ui/drop/lint-if-let-rescope-false-positives.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//@ edition: 2021
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
#![deny(if_let_rescope)]
|
||||||
|
|
||||||
|
struct Drop;
|
||||||
|
impl std::ops::Drop for Drop {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
println!("drop")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop {
|
||||||
|
fn as_ref(&self) -> Option<i32> {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn consume(_: impl Sized) -> Option<i32> { Some(1) }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let drop = Drop;
|
||||||
|
|
||||||
|
// Make sure we don't drop if we don't actually make a temporary.
|
||||||
|
if let None = drop.as_ref() {} else {}
|
||||||
|
|
||||||
|
// Make sure we don't lint if we consume the droppy value.
|
||||||
|
if let None = consume(Drop) {} else {}
|
||||||
|
|
||||||
|
// Make sure we don't lint on field exprs of place exprs.
|
||||||
|
let tup_place = (Drop, ());
|
||||||
|
if let None = consume(tup_place.1) {} else {}
|
||||||
|
}
|
|
@ -94,6 +94,12 @@ fn main() {
|
||||||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match Some((droppy(), ()).1) { Some(_value) => {} _ => {}}
|
||||||
|
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
|
||||||
|
//~| WARN: this changes meaning in Rust 2024
|
||||||
|
//~| HELP: the value is now dropped here in Edition 2024
|
||||||
|
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||||
|
|
||||||
// We want to keep the `if let`s below as direct descendents of match arms,
|
// We want to keep the `if let`s below as direct descendents of match arms,
|
||||||
// so the formatting is suppressed.
|
// so the formatting is suppressed.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
@ -94,6 +94,12 @@ fn main() {
|
||||||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||||
|
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
|
||||||
|
//~| WARN: this changes meaning in Rust 2024
|
||||||
|
//~| HELP: the value is now dropped here in Edition 2024
|
||||||
|
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||||
|
|
||||||
// We want to keep the `if let`s below as direct descendents of match arms,
|
// We want to keep the `if let`s below as direct descendents of match arms,
|
||||||
// so the formatting is suppressed.
|
// so the formatting is suppressed.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
@ -175,5 +175,26 @@ LL - while (if let Some(_value) = droppy().get() { false } else { true }) {
|
||||||
LL + while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
|
LL + while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: `if let` assigns a shorter lifetime since Edition 2024
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:97:8
|
||||||
|
|
|
||||||
|
LL | if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^
|
||||||
|
| |
|
||||||
|
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
||||||
|
|
|
||||||
|
= warning: this changes meaning in Rust 2024
|
||||||
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||||
|
help: the value is now dropped here in Edition 2024
|
||||||
|
--> $DIR/lint-if-let-rescope.rs:97:51
|
||||||
|
|
|
||||||
|
LL | if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||||
|
| ^
|
||||||
|
help: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||||
|
|
|
||||||
|
LL - if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||||
|
LL + match Some((droppy(), ()).1) { Some(_value) => {} _ => {}}
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
#![allow(internal_features)]
|
#![allow(internal_features)]
|
||||||
|
|
||||||
#[rustc_force_inline]
|
#[rustc_force_inline]
|
||||||
//~^ ERROR #![rustc_force_inline] forces a free function to be inlined
|
//~^ ERROR #[rustc_force_inline] forces a free function to be inlined
|
||||||
pub fn bare() {
|
pub fn bare() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_force_inline = "the test requires it"]
|
#[rustc_force_inline = "the test requires it"]
|
||||||
//~^ ERROR #![rustc_force_inline] forces a free function to be inlined
|
//~^ ERROR #[rustc_force_inline] forces a free function to be inlined
|
||||||
pub fn justified() {
|
pub fn justified() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error[E0658]: #![rustc_force_inline] forces a free function to be inlined
|
error[E0658]: #[rustc_force_inline] forces a free function to be inlined
|
||||||
--> $DIR/gate.rs:4:1
|
--> $DIR/gate.rs:4:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_force_inline]
|
LL | #[rustc_force_inline]
|
||||||
|
@ -7,7 +7,7 @@ LL | #[rustc_force_inline]
|
||||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: #![rustc_force_inline] forces a free function to be inlined
|
error[E0658]: #[rustc_force_inline] forces a free function to be inlined
|
||||||
--> $DIR/gate.rs:9:1
|
--> $DIR/gate.rs:9:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_force_inline = "the test requires it"]
|
LL | #[rustc_force_inline = "the test requires it"]
|
||||||
|
|
|
@ -48,13 +48,6 @@ unsafe fn simd_flog10<T>(x: T) -> T;
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
unsafe fn simd_flog2<T>(x: T) -> T;
|
unsafe fn simd_flog2<T>(x: T) -> T;
|
||||||
|
|
||||||
#[rustc_intrinsic]
|
|
||||||
unsafe fn simd_fpow<T>(x: T, y: T) -> T;
|
|
||||||
|
|
||||||
#[rustc_intrinsic]
|
|
||||||
unsafe fn simd_fpowi<T>(x: T, y: i32) -> T;
|
|
||||||
|
|
||||||
|
|
||||||
// rounding functions
|
// rounding functions
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
unsafe fn simd_ceil<T>(x: T) -> T;
|
unsafe fn simd_ceil<T>(x: T) -> T;
|
||||||
|
@ -68,23 +61,21 @@ unsafe fn simd_round<T>(x: T) -> T;
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
unsafe fn simd_trunc<T>(x: T) -> T;
|
unsafe fn simd_trunc<T>(x: T) -> T;
|
||||||
|
|
||||||
|
|
||||||
macro_rules! assert_approx_eq_f32 {
|
macro_rules! assert_approx_eq_f32 {
|
||||||
($a:expr, $b:expr) => ({
|
($a:expr, $b:expr) => {{
|
||||||
let (a, b) = (&$a, &$b);
|
let (a, b) = (&$a, &$b);
|
||||||
assert!((*a - *b).abs() < 1.0e-6,
|
assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
|
||||||
"{} is not approximately equal to {}", *a, *b);
|
}};
|
||||||
})
|
|
||||||
}
|
}
|
||||||
macro_rules! assert_approx_eq {
|
macro_rules! assert_approx_eq {
|
||||||
($a:expr, $b:expr) => ({
|
($a:expr, $b:expr) => {{
|
||||||
let a = $a;
|
let a = $a;
|
||||||
let b = $b;
|
let b = $b;
|
||||||
assert_approx_eq_f32!(a.0[0], b.0[0]);
|
assert_approx_eq_f32!(a.0[0], b.0[0]);
|
||||||
assert_approx_eq_f32!(a.0[1], b.0[1]);
|
assert_approx_eq_f32!(a.0[1], b.0[1]);
|
||||||
assert_approx_eq_f32!(a.0[2], b.0[2]);
|
assert_approx_eq_f32!(a.0[2], b.0[2]);
|
||||||
assert_approx_eq_f32!(a.0[3], b.0[3]);
|
assert_approx_eq_f32!(a.0[3], b.0[3]);
|
||||||
})
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -125,12 +116,6 @@ fn main() {
|
||||||
let r = simd_flog10(x);
|
let r = simd_flog10(x);
|
||||||
assert_approx_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
|
|
||||||
let r = simd_fpow(h, x);
|
|
||||||
assert_approx_eq!(h, r);
|
|
||||||
|
|
||||||
let r = simd_fpowi(h, 1);
|
|
||||||
assert_approx_eq!(h, r);
|
|
||||||
|
|
||||||
let r = simd_fsin(z);
|
let r = simd_fsin(z);
|
||||||
assert_approx_eq!(z, r);
|
assert_approx_eq!(z, r);
|
||||||
|
|
||||||
|
|
7
tests/ui/typeck/auxiliary/derive-demo-issue-136343.rs
Normal file
7
tests/ui/typeck/auxiliary/derive-demo-issue-136343.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
extern crate proc_macro;
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
|
#[proc_macro_derive(Sample)]
|
||||||
|
pub fn sample(_: TokenStream) -> TokenStream {
|
||||||
|
"fn bad<T: Into<U>, U>(a: T) -> U { a }".parse().unwrap()
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
//@ proc-macro: derive-demo-issue-136343.rs
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate derive_demo_issue_136343;
|
||||||
|
|
||||||
|
#[derive(Sample)] //~ ERROR mismatched types
|
||||||
|
struct Test;
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,19 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/invalid-sugg-for-derive-macro-issue-136343.rs:6:10
|
||||||
|
|
|
||||||
|
LL | #[derive(Sample)]
|
||||||
|
| ^^^^^^
|
||||||
|
| |
|
||||||
|
| expected type parameter `U`, found type parameter `T`
|
||||||
|
| expected `U` because of return type
|
||||||
|
|
|
||||||
|
= note: expected type parameter `U`
|
||||||
|
found type parameter `T`
|
||||||
|
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
||||||
|
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||||
|
= note: the caller chooses a type for `U` which can be different from `T`
|
||||||
|
= note: this error originates in the derive macro `Sample` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue