Auto merge of #78387 - Dylan-DPC:rollup-ch0st6z, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #74477 (`#[deny(unsafe_op_in_unsafe_fn)]` in sys/wasm) - #77836 (transmute_copy: explain that alignment is handled correctly) - #78126 (Properly define va_arg and va_list for aarch64-apple-darwin) - #78137 (Initialize tracing subscriber in compiletest tool) - #78161 (Add issue template link to IRLO) - #78214 (Tweak match arm semicolon removal suggestion to account for futures) - #78247 (Fix #78192) - #78252 (Add codegen test for #45964) - #78268 (Do not try to report on closures to avoid ICE) - #78295 (Add some regression tests) Failed merges: r? `@ghost`
This commit is contained in:
commit
1cd97cad6e
51 changed files with 917 additions and 372 deletions
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,5 +1,8 @@
|
||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Rust Programming Language Forum
|
- name: Question
|
||||||
url: https://users.rust-lang.org
|
url: https://users.rust-lang.org
|
||||||
about: Please ask and answer questions about Rust here.
|
about: Please ask and answer questions about Rust on the user forum.
|
||||||
|
- name: Feature Request
|
||||||
|
url: https://internals.rust-lang.org/
|
||||||
|
about: Please discuss language feature requests on the internals forum.
|
||||||
|
|
|
@ -649,7 +649,6 @@ name = "compiletest"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diff",
|
"diff",
|
||||||
"env_logger 0.7.1",
|
|
||||||
"getopts",
|
"getopts",
|
||||||
"glob",
|
"glob",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -660,6 +659,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
|
@ -173,26 +173,24 @@ pub(super) fn emit_va_arg(
|
||||||
// is lacking in some instances, so we should only use it as a fallback.
|
// is lacking in some instances, so we should only use it as a fallback.
|
||||||
let target = &bx.cx.tcx.sess.target;
|
let target = &bx.cx.tcx.sess.target;
|
||||||
let arch = &bx.cx.tcx.sess.target.arch;
|
let arch = &bx.cx.tcx.sess.target.arch;
|
||||||
match (&**arch, target.options.is_like_windows) {
|
match &**arch {
|
||||||
// Windows x86
|
// Windows x86
|
||||||
("x86", true) => {
|
"x86" if target.options.is_like_windows => {
|
||||||
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false)
|
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false)
|
||||||
}
|
}
|
||||||
// Generic x86
|
// Generic x86
|
||||||
("x86", _) => {
|
"x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true),
|
||||||
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true)
|
|
||||||
}
|
|
||||||
// Windows AArch64
|
// Windows AArch64
|
||||||
("aarch64", true) => {
|
"aarch64" if target.options.is_like_windows => {
|
||||||
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false)
|
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false)
|
||||||
}
|
}
|
||||||
// iOS AArch64
|
// macOS / iOS AArch64
|
||||||
("aarch64", _) if target.target_os == "ios" => {
|
"aarch64" if target.options.is_like_osx => {
|
||||||
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
|
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
|
||||||
}
|
}
|
||||||
("aarch64", _) => emit_aapcs_va_arg(bx, addr, target_ty),
|
"aarch64" => emit_aapcs_va_arg(bx, addr, target_ty),
|
||||||
// Windows x86_64
|
// Windows x86_64
|
||||||
("x86_64", true) => {
|
"x86_64" if target.options.is_like_windows => {
|
||||||
let target_ty_size = bx.cx.size_of(target_ty).bytes();
|
let target_ty_size = bx.cx.size_of(target_ty).bytes();
|
||||||
let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two();
|
let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two();
|
||||||
emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false)
|
emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false)
|
||||||
|
|
|
@ -50,10 +50,10 @@ use super::region_constraints::GenericKind;
|
||||||
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
|
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
|
||||||
|
|
||||||
use crate::infer;
|
use crate::infer;
|
||||||
use crate::infer::OriginalQueryValues;
|
|
||||||
use crate::traits::error_reporting::report_object_safety_error;
|
use crate::traits::error_reporting::report_object_safety_error;
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||||
|
StatementAsExpression,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
|
@ -64,7 +64,6 @@ use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::{Item, ItemKind, Node};
|
use rustc_hir::{Item, ItemKind, Node};
|
||||||
use rustc_middle::ty::error::TypeError;
|
use rustc_middle::ty::error::TypeError;
|
||||||
use rustc_middle::ty::ParamEnvAnd;
|
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self,
|
self,
|
||||||
subst::{Subst, SubstsRef},
|
subst::{Subst, SubstsRef},
|
||||||
|
@ -688,13 +687,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
let msg = "`match` arms have incompatible types";
|
let msg = "`match` arms have incompatible types";
|
||||||
err.span_label(outer_error_span, msg);
|
err.span_label(outer_error_span, msg);
|
||||||
if let Some(sp) = semi_span {
|
if let Some((sp, boxed)) = semi_span {
|
||||||
err.span_suggestion_short(
|
if let (StatementAsExpression::NeedsBoxing, [.., prior_arm]) =
|
||||||
sp,
|
(boxed, &prior_arms[..])
|
||||||
"consider removing this semicolon",
|
{
|
||||||
String::new(),
|
err.multipart_suggestion(
|
||||||
Applicability::MachineApplicable,
|
"consider removing this semicolon and boxing the expressions",
|
||||||
);
|
vec![
|
||||||
|
(prior_arm.shrink_to_lo(), "Box::new(".to_string()),
|
||||||
|
(prior_arm.shrink_to_hi(), ")".to_string()),
|
||||||
|
(arm_span.shrink_to_lo(), "Box::new(".to_string()),
|
||||||
|
(arm_span.shrink_to_hi(), ")".to_string()),
|
||||||
|
(sp, String::new()),
|
||||||
|
],
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
} else if matches!(boxed, StatementAsExpression::NeedsBoxing) {
|
||||||
|
err.span_suggestion_short(
|
||||||
|
sp,
|
||||||
|
"consider removing this semicolon and boxing the expressions",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_suggestion_short(
|
||||||
|
sp,
|
||||||
|
"consider removing this semicolon",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(ret_sp) = opt_suggest_box_span {
|
if let Some(ret_sp) = opt_suggest_box_span {
|
||||||
// Get return type span and point to it.
|
// Get return type span and point to it.
|
||||||
|
@ -717,13 +739,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
if let Some(sp) = outer {
|
if let Some(sp) = outer {
|
||||||
err.span_label(sp, "`if` and `else` have incompatible types");
|
err.span_label(sp, "`if` and `else` have incompatible types");
|
||||||
}
|
}
|
||||||
if let Some(sp) = semicolon {
|
if let Some((sp, boxed)) = semicolon {
|
||||||
err.span_suggestion_short(
|
if matches!(boxed, StatementAsExpression::NeedsBoxing) {
|
||||||
sp,
|
err.multipart_suggestion(
|
||||||
"consider removing this semicolon",
|
"consider removing this semicolon and boxing the expression",
|
||||||
String::new(),
|
vec![
|
||||||
Applicability::MachineApplicable,
|
(then.shrink_to_lo(), "Box::new(".to_string()),
|
||||||
);
|
(then.shrink_to_hi(), ")".to_string()),
|
||||||
|
(else_sp.shrink_to_lo(), "Box::new(".to_string()),
|
||||||
|
(else_sp.shrink_to_hi(), ")".to_string()),
|
||||||
|
(sp, String::new()),
|
||||||
|
],
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_suggestion_short(
|
||||||
|
sp,
|
||||||
|
"consider removing this semicolon",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(ret_sp) = opt_suggest_box_span {
|
if let Some(ret_sp) = opt_suggest_box_span {
|
||||||
self.suggest_boxing_for_return_impl_trait(
|
self.suggest_boxing_for_return_impl_trait(
|
||||||
|
@ -1602,6 +1638,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
Mismatch::Variable(exp_found) => Some(exp_found),
|
Mismatch::Variable(exp_found) => Some(exp_found),
|
||||||
Mismatch::Fixed(_) => None,
|
Mismatch::Fixed(_) => None,
|
||||||
};
|
};
|
||||||
|
let exp_found = match terr {
|
||||||
|
// `terr` has more accurate type information than `exp_found` in match expressions.
|
||||||
|
ty::error::TypeError::Sorts(terr)
|
||||||
|
if exp_found.map_or(false, |ef| terr.found == ef.found) =>
|
||||||
|
{
|
||||||
|
Some(*terr)
|
||||||
|
}
|
||||||
|
_ => exp_found,
|
||||||
|
};
|
||||||
|
debug!("exp_found {:?} terr {:?}", exp_found, terr);
|
||||||
if let Some(exp_found) = exp_found {
|
if let Some(exp_found) = exp_found {
|
||||||
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
|
||||||
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
|
self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
|
||||||
|
@ -1623,19 +1669,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
self.note_error_origin(diag, cause, exp_found);
|
self.note_error_origin(diag, cause, exp_found);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_await_on_expect_found(
|
fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||||
&self,
|
if let ty::Opaque(def_id, substs) = ty.kind() {
|
||||||
cause: &ObligationCause<'tcx>,
|
|
||||||
exp_span: Span,
|
|
||||||
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
|
||||||
diag: &mut DiagnosticBuilder<'tcx>,
|
|
||||||
) {
|
|
||||||
debug!(
|
|
||||||
"suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
|
|
||||||
exp_span, exp_found.expected, exp_found.found
|
|
||||||
);
|
|
||||||
|
|
||||||
if let ty::Opaque(def_id, _) = *exp_found.expected.kind() {
|
|
||||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||||
// Future::Output
|
// Future::Output
|
||||||
let item_def_id = self
|
let item_def_id = self
|
||||||
|
@ -1646,37 +1681,121 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.def_id;
|
.def_id;
|
||||||
|
|
||||||
let projection_ty = self.tcx.projection_ty_from_predicates((def_id, item_def_id));
|
let bounds = self.tcx.explicit_item_bounds(*def_id);
|
||||||
if let Some(projection_ty) = projection_ty {
|
|
||||||
let projection_query = self.canonicalize_query(
|
for (predicate, _) in bounds {
|
||||||
&ParamEnvAnd { param_env: self.tcx.param_env(def_id), value: projection_ty },
|
let predicate = predicate.subst(self.tcx, substs);
|
||||||
&mut OriginalQueryValues::default(),
|
if let ty::PredicateAtom::Projection(projection_predicate) =
|
||||||
);
|
predicate.skip_binders()
|
||||||
if let Ok(resp) = self.tcx.normalize_projection_ty(projection_query) {
|
{
|
||||||
let normalized_ty = resp.value.value.normalized_ty;
|
if projection_predicate.projection_ty.item_def_id == item_def_id {
|
||||||
debug!("suggest_await_on_expect_found: normalized={:?}", normalized_ty);
|
// We don't account for multiple `Future::Output = Ty` contraints.
|
||||||
if ty::TyS::same_type(normalized_ty, exp_found.found) {
|
return Some(projection_predicate.ty);
|
||||||
let span = if let ObligationCauseCode::Pattern {
|
|
||||||
span,
|
|
||||||
origin_expr: _,
|
|
||||||
root_ty: _,
|
|
||||||
} = cause.code
|
|
||||||
{
|
|
||||||
// scrutinee's span
|
|
||||||
span.unwrap_or(exp_span)
|
|
||||||
} else {
|
|
||||||
exp_span
|
|
||||||
};
|
|
||||||
diag.span_suggestion_verbose(
|
|
||||||
span.shrink_to_hi(),
|
|
||||||
"consider awaiting on the future",
|
|
||||||
".await".to_string(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A possible error is to forget to add `.await` when using futures:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// async fn make_u32() -> u32 {
|
||||||
|
/// 22
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn take_u32(x: u32) {}
|
||||||
|
///
|
||||||
|
/// async fn foo() {
|
||||||
|
/// let x = make_u32();
|
||||||
|
/// take_u32(x);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
|
||||||
|
/// expected type. If this is the case, and we are inside of an async body, it suggests adding
|
||||||
|
/// `.await` to the tail of the expression.
|
||||||
|
fn suggest_await_on_expect_found(
|
||||||
|
&self,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
exp_span: Span,
|
||||||
|
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
|
||||||
|
diag: &mut DiagnosticBuilder<'tcx>,
|
||||||
|
) {
|
||||||
|
debug!(
|
||||||
|
"suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
|
||||||
|
exp_span, exp_found.expected, exp_found.found,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let ObligationCauseCode::CompareImplMethodObligation { .. } = &cause.code {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match (
|
||||||
|
self.get_impl_future_output_ty(exp_found.expected),
|
||||||
|
self.get_impl_future_output_ty(exp_found.found),
|
||||||
|
) {
|
||||||
|
(Some(exp), Some(found)) if ty::TyS::same_type(exp, found) => match &cause.code {
|
||||||
|
ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {
|
||||||
|
diag.multipart_suggestion(
|
||||||
|
"consider `await`ing on both `Future`s",
|
||||||
|
vec![
|
||||||
|
(then.shrink_to_hi(), ".await".to_string()),
|
||||||
|
(exp_span.shrink_to_hi(), ".await".to_string()),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
|
||||||
|
prior_arms,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
if let [.., arm_span] = &prior_arms[..] {
|
||||||
|
diag.multipart_suggestion(
|
||||||
|
"consider `await`ing on both `Future`s",
|
||||||
|
vec![
|
||||||
|
(arm_span.shrink_to_hi(), ".await".to_string()),
|
||||||
|
(exp_span.shrink_to_hi(), ".await".to_string()),
|
||||||
|
],
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
diag.help("consider `await`ing on both `Future`s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
diag.help("consider `await`ing on both `Future`s");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_, Some(ty)) if ty::TyS::same_type(exp_found.expected, ty) => {
|
||||||
|
let span = match cause.code {
|
||||||
|
// scrutinee's span
|
||||||
|
ObligationCauseCode::Pattern { span: Some(span), .. } => span,
|
||||||
|
_ => exp_span,
|
||||||
|
};
|
||||||
|
diag.span_suggestion_verbose(
|
||||||
|
span.shrink_to_hi(),
|
||||||
|
"consider `await`ing on the `Future`",
|
||||||
|
".await".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(Some(ty), _) if ty::TyS::same_type(ty, exp_found.found) => {
|
||||||
|
let span = match cause.code {
|
||||||
|
// scrutinee's span
|
||||||
|
ObligationCauseCode::Pattern { span: Some(span), .. } => span,
|
||||||
|
_ => exp_span,
|
||||||
|
};
|
||||||
|
diag.span_suggestion_verbose(
|
||||||
|
span.shrink_to_hi(),
|
||||||
|
"consider `await`ing on the `Future`",
|
||||||
|
".await".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
|
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
|
||||||
|
|
|
@ -39,6 +39,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
) if **sub_r == RegionKind::ReStatic => {
|
) if **sub_r == RegionKind::ReStatic => {
|
||||||
// This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
|
// This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
|
||||||
if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
|
if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
|
||||||
|
// This may have a closure and it would cause ICE
|
||||||
|
// through `find_param_with_region` (#78262).
|
||||||
|
let anon_reg_sup = tcx.is_suitable_region(sup_r)?;
|
||||||
|
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
||||||
|
if fn_returns.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let param = self.find_param_with_region(sup_r, sub_r)?;
|
let param = self.find_param_with_region(sup_r, sub_r)?;
|
||||||
let lifetime = if sup_r.has_name() {
|
let lifetime = if sup_r.has_name() {
|
||||||
format!("lifetime `{}`", sup_r)
|
format!("lifetime `{}`", sup_r)
|
||||||
|
|
|
@ -340,11 +340,24 @@ impl ObligationCauseCode<'_> {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
static_assert_size!(ObligationCauseCode<'_>, 32);
|
static_assert_size!(ObligationCauseCode<'_>, 32);
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum StatementAsExpression {
|
||||||
|
CorrectType,
|
||||||
|
NeedsBoxing,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ty::Lift<'tcx> for StatementAsExpression {
|
||||||
|
type Lifted = StatementAsExpression;
|
||||||
|
fn lift_to_tcx(self, _tcx: TyCtxt<'tcx>) -> Option<StatementAsExpression> {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
|
||||||
pub struct MatchExpressionArmCause<'tcx> {
|
pub struct MatchExpressionArmCause<'tcx> {
|
||||||
pub arm_span: Span,
|
pub arm_span: Span,
|
||||||
pub scrut_span: Span,
|
pub scrut_span: Span,
|
||||||
pub semi_span: Option<Span>,
|
pub semi_span: Option<(Span, StatementAsExpression)>,
|
||||||
pub source: hir::MatchSource,
|
pub source: hir::MatchSource,
|
||||||
pub prior_arms: Vec<Span>,
|
pub prior_arms: Vec<Span>,
|
||||||
pub last_ty: Ty<'tcx>,
|
pub last_ty: Ty<'tcx>,
|
||||||
|
@ -357,7 +370,7 @@ pub struct IfExpressionCause {
|
||||||
pub then: Span,
|
pub then: Span,
|
||||||
pub else_sp: Span,
|
pub else_sp: Span,
|
||||||
pub outer: Option<Span>,
|
pub outer: Option<Span>,
|
||||||
pub semicolon: Option<Span>,
|
pub semicolon: Option<(Span, StatementAsExpression)>,
|
||||||
pub opt_suggest_box_span: Option<Span>,
|
pub opt_suggest_box_span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,26 +334,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
|
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
|
||||||
match err {
|
match err {
|
||||||
Sorts(values) => {
|
Sorts(values) => {
|
||||||
let expected_str = values.expected.sort_string(self);
|
|
||||||
let found_str = values.found.sort_string(self);
|
|
||||||
if expected_str == found_str && expected_str == "closure" {
|
|
||||||
db.note("no two closures, even if identical, have the same type");
|
|
||||||
db.help("consider boxing your closure and/or using it as a trait object");
|
|
||||||
}
|
|
||||||
if expected_str == found_str && expected_str == "opaque type" {
|
|
||||||
// Issue #63167
|
|
||||||
db.note("distinct uses of `impl Trait` result in different opaque types");
|
|
||||||
let e_str = values.expected.to_string();
|
|
||||||
let f_str = values.found.to_string();
|
|
||||||
if e_str == f_str && &e_str == "impl std::future::Future" {
|
|
||||||
// FIXME: use non-string based check.
|
|
||||||
db.help(
|
|
||||||
"if both `Future`s have the same `Output` type, consider \
|
|
||||||
`.await`ing on both of them",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match (values.expected.kind(), values.found.kind()) {
|
match (values.expected.kind(), values.found.kind()) {
|
||||||
|
(ty::Closure(..), ty::Closure(..)) => {
|
||||||
|
db.note("no two closures, even if identical, have the same type");
|
||||||
|
db.help("consider boxing your closure and/or using it as a trait object");
|
||||||
|
}
|
||||||
|
(ty::Opaque(..), ty::Opaque(..)) => {
|
||||||
|
// Issue #63167
|
||||||
|
db.note("distinct uses of `impl Trait` result in different opaque types");
|
||||||
|
}
|
||||||
(ty::Float(_), ty::Infer(ty::IntVar(_))) => {
|
(ty::Float(_), ty::Infer(ty::IntVar(_))) => {
|
||||||
if let Ok(
|
if let Ok(
|
||||||
// Issue #53280
|
// Issue #53280
|
||||||
|
@ -382,12 +371,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
db.note(
|
db.note(
|
||||||
"a type parameter was expected, but a different one was found; \
|
"a type parameter was expected, but a different one was found; \
|
||||||
you might be missing a type parameter or trait bound",
|
you might be missing a type parameter or trait bound",
|
||||||
);
|
);
|
||||||
db.note(
|
db.note(
|
||||||
"for more information, visit \
|
"for more information, visit \
|
||||||
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
||||||
#traits-as-parameters",
|
#traits-as-parameters",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(ty::Projection(_), ty::Projection(_)) => {
|
(ty::Projection(_), ty::Projection(_)) => {
|
||||||
|
@ -471,8 +460,8 @@ impl<T> Trait<T> for X {
|
||||||
}
|
}
|
||||||
db.note(
|
db.note(
|
||||||
"for more information, visit \
|
"for more information, visit \
|
||||||
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
||||||
#traits-as-parameters",
|
#traits-as-parameters",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
|
(ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
|
||||||
|
|
|
@ -119,11 +119,6 @@ impl OptimizationFinder<'b, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_deref_of_address(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> {
|
fn find_deref_of_address(&mut self, rvalue: &Rvalue<'tcx>, location: Location) -> Option<()> {
|
||||||
// FIXME(#78192): This optimization can result in unsoundness.
|
|
||||||
if !self.tcx.sess.opts.debugging_opts.unsound_mir_opts {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the sequence
|
// Look for the sequence
|
||||||
//
|
//
|
||||||
// _2 = &_1;
|
// _2 = &_1;
|
||||||
|
@ -137,6 +132,8 @@ impl OptimizationFinder<'b, 'tcx> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
let mut dead_locals_seen = vec![];
|
||||||
|
|
||||||
let stmt_index = location.statement_index;
|
let stmt_index = location.statement_index;
|
||||||
// Look behind for statement that assigns the local from a address of operator.
|
// Look behind for statement that assigns the local from a address of operator.
|
||||||
// 6 is chosen as a heuristic determined by seeing the number of times
|
// 6 is chosen as a heuristic determined by seeing the number of times
|
||||||
|
@ -160,6 +157,11 @@ impl OptimizationFinder<'b, 'tcx> {
|
||||||
BorrowKind::Shared,
|
BorrowKind::Shared,
|
||||||
place_taken_address_of,
|
place_taken_address_of,
|
||||||
) => {
|
) => {
|
||||||
|
// Make sure that the place has not been marked dead
|
||||||
|
if dead_locals_seen.contains(&place_taken_address_of.local) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
self.optimizations
|
self.optimizations
|
||||||
.unneeded_deref
|
.unneeded_deref
|
||||||
.insert(location, *place_taken_address_of);
|
.insert(location, *place_taken_address_of);
|
||||||
|
@ -178,13 +180,19 @@ impl OptimizationFinder<'b, 'tcx> {
|
||||||
// Inline asm can do anything, so bail out of the optimization.
|
// Inline asm can do anything, so bail out of the optimization.
|
||||||
rustc_middle::mir::StatementKind::LlvmInlineAsm(_) => return None,
|
rustc_middle::mir::StatementKind::LlvmInlineAsm(_) => return None,
|
||||||
|
|
||||||
|
// Remember `StorageDead`s, as the local being marked dead could be the
|
||||||
|
// place RHS we are looking for, in which case we need to abort to avoid UB
|
||||||
|
// using an uninitialized place
|
||||||
|
rustc_middle::mir::StatementKind::StorageDead(dead) => {
|
||||||
|
dead_locals_seen.push(*dead)
|
||||||
|
}
|
||||||
|
|
||||||
// Check that `local_being_deref` is not being used in a mutating way which can cause misoptimization.
|
// Check that `local_being_deref` is not being used in a mutating way which can cause misoptimization.
|
||||||
rustc_middle::mir::StatementKind::Assign(box (_, _))
|
rustc_middle::mir::StatementKind::Assign(box (_, _))
|
||||||
| rustc_middle::mir::StatementKind::Coverage(_)
|
| rustc_middle::mir::StatementKind::Coverage(_)
|
||||||
| rustc_middle::mir::StatementKind::Nop
|
| rustc_middle::mir::StatementKind::Nop
|
||||||
| rustc_middle::mir::StatementKind::FakeRead(_, _)
|
| rustc_middle::mir::StatementKind::FakeRead(_, _)
|
||||||
| rustc_middle::mir::StatementKind::StorageLive(_)
|
| rustc_middle::mir::StatementKind::StorageLive(_)
|
||||||
| rustc_middle::mir::StatementKind::StorageDead(_)
|
|
||||||
| rustc_middle::mir::StatementKind::Retag(_, _)
|
| rustc_middle::mir::StatementKind::Retag(_, _)
|
||||||
| rustc_middle::mir::StatementKind::AscribeUserType(_, _)
|
| rustc_middle::mir::StatementKind::AscribeUserType(_, _)
|
||||||
| rustc_middle::mir::StatementKind::SetDiscriminant { .. } => {
|
| rustc_middle::mir::StatementKind::SetDiscriminant { .. } => {
|
||||||
|
|
|
@ -1207,7 +1207,13 @@ impl<'a> Parser<'a> {
|
||||||
self.recover_await_prefix(await_sp)?
|
self.recover_await_prefix(await_sp)?
|
||||||
};
|
};
|
||||||
let sp = self.error_on_incorrect_await(lo, hi, &expr, is_question);
|
let sp = self.error_on_incorrect_await(lo, hi, &expr, is_question);
|
||||||
let expr = self.mk_expr(lo.to(sp), ExprKind::Await(expr), attrs);
|
let kind = match expr.kind {
|
||||||
|
// Avoid knock-down errors as we don't know whether to interpret this as `foo().await?`
|
||||||
|
// or `foo()?.await` (the very reason we went with postfix syntax 😅).
|
||||||
|
ExprKind::Try(_) => ExprKind::Err,
|
||||||
|
_ => ExprKind::Await(expr),
|
||||||
|
};
|
||||||
|
let expr = self.mk_expr(lo.to(sp), kind, attrs);
|
||||||
self.maybe_recover_from_bad_qpath(expr, true)
|
self.maybe_recover_from_bad_qpath(expr, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ use rustc_middle::ty::{
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{MultiSpan, Span, DUMMY_SP};
|
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -2114,10 +2114,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
if self.predicate_may_hold(&try_obligation) && impls_future {
|
if self.predicate_may_hold(&try_obligation) && impls_future {
|
||||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
if snippet.ends_with('?') {
|
if snippet.ends_with('?') {
|
||||||
err.span_suggestion(
|
err.span_suggestion_verbose(
|
||||||
span,
|
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
|
||||||
"consider using `.await` here",
|
"consider `await`ing on the `Future`",
|
||||||
format!("{}.await?", snippet.trim_end_matches('?')),
|
".await".to_string(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use rustc_trait_selection::opaque_types::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{
|
||||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||||
|
StatementAsExpression,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
@ -188,11 +189,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (arm_span, semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind {
|
let (arm_span, semi_span) =
|
||||||
self.find_block_span(blk, prior_arm_ty)
|
self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty);
|
||||||
} else {
|
|
||||||
(arm.body.span, None)
|
|
||||||
};
|
|
||||||
let (span, code) = match i {
|
let (span, code) = match i {
|
||||||
// The reason for the first arm to fail is not that the match arms diverge,
|
// The reason for the first arm to fail is not that the match arms diverge,
|
||||||
// but rather that there's a prior obligation that doesn't hold.
|
// but rather that there's a prior obligation that doesn't hold.
|
||||||
|
@ -242,6 +240,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
coercion.complete(self)
|
coercion.complete(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_appropriate_arm_semicolon_removal_span(
|
||||||
|
&self,
|
||||||
|
arms: &'tcx [hir::Arm<'tcx>],
|
||||||
|
i: usize,
|
||||||
|
prior_arm_ty: Option<Ty<'tcx>>,
|
||||||
|
arm_ty: Ty<'tcx>,
|
||||||
|
) -> (Span, Option<(Span, StatementAsExpression)>) {
|
||||||
|
let arm = &arms[i];
|
||||||
|
let (arm_span, mut semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind {
|
||||||
|
self.find_block_span(blk, prior_arm_ty)
|
||||||
|
} else {
|
||||||
|
(arm.body.span, None)
|
||||||
|
};
|
||||||
|
if semi_span.is_none() && i > 0 {
|
||||||
|
if let hir::ExprKind::Block(blk, _) = &arms[i - 1].body.kind {
|
||||||
|
let (_, semi_span_prev) = self.find_block_span(blk, Some(arm_ty));
|
||||||
|
semi_span = semi_span_prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(arm_span, semi_span)
|
||||||
|
}
|
||||||
|
|
||||||
/// When the previously checked expression (the scrutinee) diverges,
|
/// When the previously checked expression (the scrutinee) diverges,
|
||||||
/// warn the user about the match arms being unreachable.
|
/// warn the user about the match arms being unreachable.
|
||||||
fn warn_arms_when_scrutinee_diverges(
|
fn warn_arms_when_scrutinee_diverges(
|
||||||
|
@ -514,7 +534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
block: &'tcx hir::Block<'tcx>,
|
block: &'tcx hir::Block<'tcx>,
|
||||||
expected_ty: Option<Ty<'tcx>>,
|
expected_ty: Option<Ty<'tcx>>,
|
||||||
) -> (Span, Option<Span>) {
|
) -> (Span, Option<(Span, StatementAsExpression)>) {
|
||||||
if let Some(expr) = &block.expr {
|
if let Some(expr) = &block.expr {
|
||||||
(expr.span, None)
|
(expr.span, None)
|
||||||
} else if let Some(stmt) = block.stmts.last() {
|
} else if let Some(stmt) = block.stmts.last() {
|
||||||
|
|
|
@ -33,7 +33,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||||
self.suggest_missing_await(err, expr, expected, expr_ty);
|
|
||||||
self.suggest_missing_parentheses(err, expr);
|
self.suggest_missing_parentheses(err, expr);
|
||||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||||
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
||||||
|
|
|
@ -33,7 +33,9 @@ use rustc_span::{self, BytePos, MultiSpan, Span};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::opaque_types::InferCtxtExt as _;
|
use rustc_trait_selection::opaque_types::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::{self, ObligationCauseCode, TraitEngine, TraitEngineExt};
|
use rustc_trait_selection::traits::{
|
||||||
|
self, ObligationCauseCode, StatementAsExpression, TraitEngine, TraitEngineExt,
|
||||||
|
};
|
||||||
|
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -1061,7 +1063,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
blk: &'tcx hir::Block<'tcx>,
|
blk: &'tcx hir::Block<'tcx>,
|
||||||
expected_ty: Ty<'tcx>,
|
expected_ty: Ty<'tcx>,
|
||||||
) -> Option<Span> {
|
) -> Option<(Span, StatementAsExpression)> {
|
||||||
// Be helpful when the user wrote `{... expr;}` and
|
// Be helpful when the user wrote `{... expr;}` and
|
||||||
// taking the `;` off is enough to fix the error.
|
// taking the `;` off is enough to fix the error.
|
||||||
let last_stmt = blk.stmts.last()?;
|
let last_stmt = blk.stmts.last()?;
|
||||||
|
@ -1070,13 +1072,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let last_expr_ty = self.node_ty(last_expr.hir_id);
|
let last_expr_ty = self.node_ty(last_expr.hir_id);
|
||||||
if matches!(last_expr_ty.kind(), ty::Error(_))
|
let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
|
||||||
|| self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err()
|
(ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
|
||||||
|
debug!(
|
||||||
|
"both opaque, likely future {:?} {:?} {:?} {:?}",
|
||||||
|
last_def_id, last_bounds, exp_def_id, exp_bounds
|
||||||
|
);
|
||||||
|
let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_def_id.expect_local());
|
||||||
|
let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_def_id.expect_local());
|
||||||
|
match (
|
||||||
|
&self.tcx.hir().expect_item(last_hir_id).kind,
|
||||||
|
&self.tcx.hir().expect_item(exp_hir_id).kind,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
|
||||||
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
|
||||||
|
) if last_bounds.iter().zip(exp_bounds.iter()).all(|(left, right)| {
|
||||||
|
match (left, right) {
|
||||||
|
(
|
||||||
|
hir::GenericBound::Trait(tl, ml),
|
||||||
|
hir::GenericBound::Trait(tr, mr),
|
||||||
|
) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
|
||||||
|
&& ml == mr =>
|
||||||
|
{
|
||||||
|
true
|
||||||
|
}
|
||||||
|
(
|
||||||
|
hir::GenericBound::LangItemTrait(langl, _, _, argsl),
|
||||||
|
hir::GenericBound::LangItemTrait(langr, _, _, argsr),
|
||||||
|
) if langl == langr => {
|
||||||
|
// FIXME: consider the bounds!
|
||||||
|
debug!("{:?} {:?}", argsl, argsr);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}) =>
|
||||||
|
{
|
||||||
|
StatementAsExpression::NeedsBoxing
|
||||||
|
}
|
||||||
|
_ => StatementAsExpression::CorrectType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => StatementAsExpression::CorrectType,
|
||||||
|
};
|
||||||
|
if (matches!(last_expr_ty.kind(), ty::Error(_))
|
||||||
|
|| self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err())
|
||||||
|
&& matches!(needs_box, StatementAsExpression::CorrectType)
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let original_span = original_sp(last_stmt.span, blk.span);
|
let original_span = original_sp(last_stmt.span, blk.span);
|
||||||
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
|
Some((original_span.with_lo(original_span.hi() - BytePos(1)), needs_box))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiates the given path, which must refer to an item with the given
|
// Instantiates the given path, which must refer to an item with the given
|
||||||
|
|
|
@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::{self, MultiSpan, Span};
|
use rustc_span::{self, MultiSpan, Span};
|
||||||
use rustc_trait_selection::traits::{self, ObligationCauseCode};
|
use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
|
||||||
|
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -758,13 +758,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
expected_ty: Ty<'tcx>,
|
expected_ty: Ty<'tcx>,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
) {
|
) {
|
||||||
if let Some(span_semi) = self.could_remove_semicolon(blk, expected_ty) {
|
if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
|
||||||
err.span_suggestion(
|
if let StatementAsExpression::NeedsBoxing = boxed {
|
||||||
span_semi,
|
err.span_suggestion_verbose(
|
||||||
"consider removing this semicolon",
|
span_semi,
|
||||||
String::new(),
|
"consider removing this semicolon and boxing the expression",
|
||||||
Applicability::MachineApplicable,
|
String::new(),
|
||||||
);
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.span_suggestion_short(
|
||||||
|
span_semi,
|
||||||
|
"consider removing this semicolon",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::astconv::AstConv;
|
||||||
|
|
||||||
use rustc_ast::util::parser::ExprPrecedence;
|
use rustc_ast::util::parser::ExprPrecedence;
|
||||||
use rustc_span::{self, Span};
|
use rustc_span::{self, Span};
|
||||||
use rustc_trait_selection::traits;
|
|
||||||
|
|
||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -13,7 +12,6 @@ use rustc_hir::{ExprKind, ItemKind, Node};
|
||||||
use rustc_infer::infer;
|
use rustc_infer::infer;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
@ -433,87 +431,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A possible error is to forget to add `.await` when using futures:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// async fn make_u32() -> u32 {
|
|
||||||
/// 22
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn take_u32(x: u32) {}
|
|
||||||
///
|
|
||||||
/// async fn foo() {
|
|
||||||
/// let x = make_u32();
|
|
||||||
/// take_u32(x);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
|
|
||||||
/// expected type. If this is the case, and we are inside of an async body, it suggests adding
|
|
||||||
/// `.await` to the tail of the expression.
|
|
||||||
pub(in super::super) fn suggest_missing_await(
|
|
||||||
&self,
|
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
|
||||||
expr: &hir::Expr<'_>,
|
|
||||||
expected: Ty<'tcx>,
|
|
||||||
found: Ty<'tcx>,
|
|
||||||
) {
|
|
||||||
debug!("suggest_missing_await: expr={:?} expected={:?}, found={:?}", expr, expected, found);
|
|
||||||
// `.await` is not permitted outside of `async` bodies, so don't bother to suggest if the
|
|
||||||
// body isn't `async`.
|
|
||||||
let item_id = self.tcx().hir().get_parent_node(self.body_id);
|
|
||||||
if let Some(body_id) = self.tcx().hir().maybe_body_owned_by(item_id) {
|
|
||||||
let body = self.tcx().hir().body(body_id);
|
|
||||||
if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
|
|
||||||
let sp = expr.span;
|
|
||||||
// Check for `Future` implementations by constructing a predicate to
|
|
||||||
// prove: `<T as Future>::Output == U`
|
|
||||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, Some(sp));
|
|
||||||
let item_def_id = self
|
|
||||||
.tcx
|
|
||||||
.associated_items(future_trait)
|
|
||||||
.in_definition_order()
|
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.def_id;
|
|
||||||
// `<T as Future>::Output`
|
|
||||||
let projection_ty = ty::ProjectionTy {
|
|
||||||
// `T`
|
|
||||||
substs: self
|
|
||||||
.tcx
|
|
||||||
.mk_substs_trait(found, self.fresh_substs_for_item(sp, item_def_id)),
|
|
||||||
// `Future::Output`
|
|
||||||
item_def_id,
|
|
||||||
};
|
|
||||||
|
|
||||||
let predicate = ty::PredicateAtom::Projection(ty::ProjectionPredicate {
|
|
||||||
projection_ty,
|
|
||||||
ty: expected,
|
|
||||||
})
|
|
||||||
.potentially_quantified(self.tcx, ty::PredicateKind::ForAll);
|
|
||||||
let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate);
|
|
||||||
|
|
||||||
debug!("suggest_missing_await: trying obligation {:?}", obligation);
|
|
||||||
|
|
||||||
if self.infcx.predicate_may_hold(&obligation) {
|
|
||||||
debug!("suggest_missing_await: obligation held: {:?}", obligation);
|
|
||||||
if let Ok(code) = self.sess().source_map().span_to_snippet(sp) {
|
|
||||||
err.span_suggestion(
|
|
||||||
sp,
|
|
||||||
"consider using `.await` here",
|
|
||||||
format!("{}.await", code),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
debug!("suggest_missing_await: no snippet for {:?}", sp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug!("suggest_missing_await: obligation did not hold: {:?}", obligation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(in super::super) fn suggest_missing_parentheses(
|
pub(in super::super) fn suggest_missing_parentheses(
|
||||||
&self,
|
&self,
|
||||||
err: &mut DiagnosticBuilder<'_>,
|
err: &mut DiagnosticBuilder<'_>,
|
||||||
|
|
|
@ -62,7 +62,7 @@ impl fmt::Debug for c_void {
|
||||||
// The name is WIP, using `VaListImpl` for now.
|
// The name is WIP, using `VaListImpl` for now.
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
||||||
all(target_arch = "aarch64", target_os = "ios"),
|
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||||
target_arch = "wasm32",
|
target_arch = "wasm32",
|
||||||
target_arch = "asmjs",
|
target_arch = "asmjs",
|
||||||
windows
|
windows
|
||||||
|
@ -85,7 +85,7 @@ pub struct VaListImpl<'f> {
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
||||||
all(target_arch = "aarch64", target_os = "ios"),
|
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||||
target_arch = "wasm32",
|
target_arch = "wasm32",
|
||||||
target_arch = "asmjs",
|
target_arch = "asmjs",
|
||||||
windows
|
windows
|
||||||
|
@ -107,7 +107,11 @@ impl<'f> fmt::Debug for VaListImpl<'f> {
|
||||||
///
|
///
|
||||||
/// [AArch64 Procedure Call Standard]:
|
/// [AArch64 Procedure Call Standard]:
|
||||||
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
|
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
|
||||||
#[cfg(all(target_arch = "aarch64", not(target_os = "ios"), not(windows)))]
|
#[cfg(all(
|
||||||
|
target_arch = "aarch64",
|
||||||
|
not(any(target_os = "macos", target_os = "ios")),
|
||||||
|
not(windows)
|
||||||
|
))]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[unstable(
|
#[unstable(
|
||||||
|
@ -181,7 +185,7 @@ pub struct VaList<'a, 'f: 'a> {
|
||||||
not(target_arch = "powerpc"),
|
not(target_arch = "powerpc"),
|
||||||
not(target_arch = "x86_64")
|
not(target_arch = "x86_64")
|
||||||
),
|
),
|
||||||
all(target_arch = "aarch64", target_os = "ios"),
|
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||||
target_arch = "wasm32",
|
target_arch = "wasm32",
|
||||||
target_arch = "asmjs",
|
target_arch = "asmjs",
|
||||||
windows
|
windows
|
||||||
|
@ -190,7 +194,7 @@ pub struct VaList<'a, 'f: 'a> {
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
|
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
|
||||||
any(not(target_arch = "aarch64"), not(target_os = "ios")),
|
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
|
||||||
not(target_arch = "wasm32"),
|
not(target_arch = "wasm32"),
|
||||||
not(target_arch = "asmjs"),
|
not(target_arch = "asmjs"),
|
||||||
not(windows)
|
not(windows)
|
||||||
|
@ -202,7 +206,7 @@ pub struct VaList<'a, 'f: 'a> {
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
||||||
all(target_arch = "aarch64", target_os = "ios"),
|
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||||
target_arch = "wasm32",
|
target_arch = "wasm32",
|
||||||
target_arch = "asmjs",
|
target_arch = "asmjs",
|
||||||
windows
|
windows
|
||||||
|
@ -223,7 +227,7 @@ impl<'f> VaListImpl<'f> {
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
|
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
|
||||||
any(not(target_arch = "aarch64"), not(target_os = "ios")),
|
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
|
||||||
not(target_arch = "wasm32"),
|
not(target_arch = "wasm32"),
|
||||||
not(target_arch = "asmjs"),
|
not(target_arch = "asmjs"),
|
||||||
not(windows)
|
not(windows)
|
||||||
|
|
|
@ -884,10 +884,10 @@ pub fn drop<T>(_x: T) {}
|
||||||
/// Interprets `src` as having type `&U`, and then reads `src` without moving
|
/// Interprets `src` as having type `&U`, and then reads `src` without moving
|
||||||
/// the contained value.
|
/// the contained value.
|
||||||
///
|
///
|
||||||
/// This function will unsafely assume the pointer `src` is valid for
|
/// This function will unsafely assume the pointer `src` is valid for [`size_of::<U>`][size_of]
|
||||||
/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading
|
/// bytes by transmuting `&T` to `&U` and then reading the `&U` (except that this is done in a way
|
||||||
/// the `&U`. It will also unsafely create a copy of the contained value instead of
|
/// that is correct even when `&U` makes stricter alignment requirements than `&T`). It will also
|
||||||
/// moving out of `src`.
|
/// unsafely create a copy of the contained value instead of moving out of `src`.
|
||||||
///
|
///
|
||||||
/// It is not a compile-time error if `T` and `U` have different sizes, but it
|
/// It is not a compile-time error if `T` and `U` have different sizes, but it
|
||||||
/// is highly encouraged to only invoke this function where `T` and `U` have the
|
/// is highly encouraged to only invoke this function where `T` and `U` have the
|
||||||
|
|
|
@ -24,26 +24,34 @@ static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
|
||||||
unsafe impl GlobalAlloc for System {
|
unsafe impl GlobalAlloc for System {
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
// SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
|
||||||
|
// Calling malloc() is safe because preconditions on this function match the trait method preconditions.
|
||||||
let _lock = lock::lock();
|
let _lock = lock::lock();
|
||||||
DLMALLOC.malloc(layout.size(), layout.align())
|
unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||||
|
// SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
|
||||||
|
// Calling calloc() is safe because preconditions on this function match the trait method preconditions.
|
||||||
let _lock = lock::lock();
|
let _lock = lock::lock();
|
||||||
DLMALLOC.calloc(layout.size(), layout.align())
|
unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
// SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
|
||||||
|
// Calling free() is safe because preconditions on this function match the trait method preconditions.
|
||||||
let _lock = lock::lock();
|
let _lock = lock::lock();
|
||||||
DLMALLOC.free(ptr, layout.size(), layout.align())
|
unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
|
// SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access.
|
||||||
|
// Calling realloc() is safe because preconditions on this function match the trait method preconditions.
|
||||||
let _lock = lock::lock();
|
let _lock = lock::lock();
|
||||||
DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
|
unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,13 +44,19 @@ impl Condvar {
|
||||||
|
|
||||||
pub unsafe fn notify_one(&self) {
|
pub unsafe fn notify_one(&self) {
|
||||||
self.cnt.fetch_add(1, SeqCst);
|
self.cnt.fetch_add(1, SeqCst);
|
||||||
wasm32::memory_atomic_notify(self.ptr(), 1);
|
// SAFETY: ptr() is always valid
|
||||||
|
unsafe {
|
||||||
|
wasm32::memory_atomic_notify(self.ptr(), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn notify_all(&self) {
|
pub unsafe fn notify_all(&self) {
|
||||||
self.cnt.fetch_add(1, SeqCst);
|
self.cnt.fetch_add(1, SeqCst);
|
||||||
wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
|
// SAFETY: ptr() is always valid
|
||||||
|
unsafe {
|
||||||
|
wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn wait(&self, mutex: &Mutex) {
|
pub unsafe fn wait(&self, mutex: &Mutex) {
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
//! compiling for wasm. That way it's a compile time error for something that's
|
//! compiling for wasm. That way it's a compile time error for something that's
|
||||||
//! guaranteed to be a runtime error!
|
//! guaranteed to be a runtime error!
|
||||||
|
|
||||||
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
#[path = "../unsupported/cmath.rs"]
|
#[path = "../unsupported/cmath.rs"]
|
||||||
|
|
|
@ -28,11 +28,14 @@ impl Mutex {
|
||||||
|
|
||||||
pub unsafe fn lock(&self) {
|
pub unsafe fn lock(&self) {
|
||||||
while !self.try_lock() {
|
while !self.try_lock() {
|
||||||
let val = wasm32::memory_atomic_wait32(
|
// SAFETY: the caller must uphold the safety contract for `memory_atomic_wait32`.
|
||||||
self.ptr(),
|
let val = unsafe {
|
||||||
1, // we expect our mutex is locked
|
wasm32::memory_atomic_wait32(
|
||||||
-1, // wait infinitely
|
self.ptr(),
|
||||||
);
|
1, // we expect our mutex is locked
|
||||||
|
-1, // wait infinitely
|
||||||
|
)
|
||||||
|
};
|
||||||
// we should have either woke up (0) or got a not-equal due to a
|
// we should have either woke up (0) or got a not-equal due to a
|
||||||
// race (1). We should never time out (2)
|
// race (1). We should never time out (2)
|
||||||
debug_assert!(val == 0 || val == 1);
|
debug_assert!(val == 0 || val == 1);
|
||||||
|
@ -93,19 +96,20 @@ impl ReentrantMutex {
|
||||||
pub unsafe fn lock(&self) {
|
pub unsafe fn lock(&self) {
|
||||||
let me = thread::my_id();
|
let me = thread::my_id();
|
||||||
while let Err(owner) = self._try_lock(me) {
|
while let Err(owner) = self._try_lock(me) {
|
||||||
let val = wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1);
|
// SAFETY: the caller must gurantee that `self.ptr()` and `owner` are valid i32.
|
||||||
|
let val = unsafe { wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1) };
|
||||||
debug_assert!(val == 0 || val == 1);
|
debug_assert!(val == 0 || val == 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn try_lock(&self) -> bool {
|
pub unsafe fn try_lock(&self) -> bool {
|
||||||
self._try_lock(thread::my_id()).is_ok()
|
unsafe { self._try_lock(thread::my_id()).is_ok() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> {
|
unsafe fn _try_lock(&self, id: u32) -> Result<(), u32> {
|
||||||
let id = id.checked_add(1).unwrap(); // make sure `id` isn't 0
|
let id = id.checked_add(1).unwrap();
|
||||||
match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
|
match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
|
||||||
// we transitioned from unlocked to locked
|
// we transitioned from unlocked to locked
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
@ -132,7 +136,10 @@ impl ReentrantMutex {
|
||||||
match *self.recursions.get() {
|
match *self.recursions.get() {
|
||||||
0 => {
|
0 => {
|
||||||
self.owner.swap(0, SeqCst);
|
self.owner.swap(0, SeqCst);
|
||||||
wasm32::memory_atomic_notify(self.ptr() as *mut i32, 1); // wake up one waiter, if any
|
// SAFETY: the caller must gurantee that `self.ptr()` is valid i32.
|
||||||
|
unsafe {
|
||||||
|
wasm32::atomic_notify(self.ptr() as *mut i32, 1);
|
||||||
|
} // wake up one waiter, if any
|
||||||
}
|
}
|
||||||
ref mut n => *n -= 1,
|
ref mut n => *n -= 1,
|
||||||
}
|
}
|
||||||
|
|
38
src/test/codegen/issue-45964-bounds-check-slice-pos.rs
Normal file
38
src/test/codegen/issue-45964-bounds-check-slice-pos.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// This test case checks that slice::{r}position functions do not
|
||||||
|
// prevent optimizing away bounds checks
|
||||||
|
|
||||||
|
// compile-flags: -O
|
||||||
|
|
||||||
|
#![crate_type="rlib"]
|
||||||
|
|
||||||
|
// CHECK-LABEL: @test
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn test(y: &[u32], x: &u32, z: &u32) -> bool {
|
||||||
|
let result = match y.iter().position(|a| a == x) {
|
||||||
|
Some(p) => Ok(p),
|
||||||
|
None => Err(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(p) = result {
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
y[p] == *z
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @rtest
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn rtest(y: &[u32], x: &u32, z: &u32) -> bool {
|
||||||
|
let result = match y.iter().rposition(|a| a == x) {
|
||||||
|
Some(p) => Ok(p),
|
||||||
|
None => Err(()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(p) = result {
|
||||||
|
// CHECK-NOT: panic
|
||||||
|
y[p] == *z
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@
|
||||||
// + span: $DIR/ref_deref.rs:5:6: 5:10
|
// + span: $DIR/ref_deref.rs:5:6: 5:10
|
||||||
// + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
// + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
||||||
_2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
|
_2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
|
||||||
- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
|
- _1 = (*_4); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
|
||||||
+ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
|
+ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
|
||||||
StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
|
StorageDead(_2); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
|
||||||
StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
|
StorageDead(_1); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
// + span: $DIR/ref_deref_project.rs:5:6: 5:17
|
// + span: $DIR/ref_deref_project.rs:5:6: 5:17
|
||||||
// + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
// + literal: Const { ty: &(i32, i32), val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
||||||
_2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
|
_2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
|
||||||
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
|
_1 = ((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
|
||||||
StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
|
StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
|
||||||
StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
|
StorageDead(_1); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
|
||||||
_0 = const (); // scope 0 at $DIR/ref_deref_project.rs:4:11: 6:2
|
_0 = const (); // scope 0 at $DIR/ref_deref_project.rs:4:11: 6:2
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// compile-flags: -O -Zunsound-mir-opts
|
// compile-flags: -O
|
||||||
// EMIT_MIR inst_combine_deref.simple_opt.InstCombine.diff
|
// EMIT_MIR inst_combine_deref.simple_opt.InstCombine.diff
|
||||||
fn simple_opt() -> u64 {
|
fn simple_opt() -> u64 {
|
||||||
let x = 5;
|
let x = 5;
|
||||||
|
|
9
src/test/mir-opt/issue-78192.rs
Normal file
9
src/test/mir-opt/issue-78192.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// EMIT_MIR issue_78192.f.InstCombine.diff
|
||||||
|
pub fn f<T>(a: &T) -> *const T {
|
||||||
|
let b: &*const T = &(a as *const T);
|
||||||
|
*b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f(&2);
|
||||||
|
}
|
29
src/test/mir-opt/issue_78192.f.InstCombine.diff
Normal file
29
src/test/mir-opt/issue_78192.f.InstCombine.diff
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
- // MIR for `f` before InstCombine
|
||||||
|
+ // MIR for `f` after InstCombine
|
||||||
|
|
||||||
|
fn f(_1: &T) -> *const T {
|
||||||
|
debug a => _1; // in scope 0 at $DIR/issue-78192.rs:2:13: 2:14
|
||||||
|
let mut _0: *const T; // return place in scope 0 at $DIR/issue-78192.rs:2:23: 2:31
|
||||||
|
let _2: &*const T; // in scope 0 at $DIR/issue-78192.rs:3:9: 3:10
|
||||||
|
let _3: &*const T; // in scope 0 at $DIR/issue-78192.rs:3:24: 3:40
|
||||||
|
let _4: *const T; // in scope 0 at $DIR/issue-78192.rs:3:25: 3:40
|
||||||
|
scope 1 {
|
||||||
|
debug b => _2; // in scope 1 at $DIR/issue-78192.rs:3:9: 3:10
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_2); // scope 0 at $DIR/issue-78192.rs:3:9: 3:10
|
||||||
|
StorageLive(_3); // scope 0 at $DIR/issue-78192.rs:3:24: 3:40
|
||||||
|
StorageLive(_4); // scope 0 at $DIR/issue-78192.rs:3:25: 3:40
|
||||||
|
_4 = &raw const (*_1); // scope 0 at $DIR/issue-78192.rs:3:26: 3:27
|
||||||
|
_3 = &_4; // scope 0 at $DIR/issue-78192.rs:3:24: 3:40
|
||||||
|
- _2 = &(*_3); // scope 0 at $DIR/issue-78192.rs:3:24: 3:40
|
||||||
|
+ _2 = _3; // scope 0 at $DIR/issue-78192.rs:3:24: 3:40
|
||||||
|
StorageDead(_3); // scope 0 at $DIR/issue-78192.rs:3:40: 3:41
|
||||||
|
_0 = (*_2); // scope 1 at $DIR/issue-78192.rs:4:5: 4:7
|
||||||
|
StorageDead(_4); // scope 0 at $DIR/issue-78192.rs:5:1: 5:2
|
||||||
|
StorageDead(_2); // scope 0 at $DIR/issue-78192.rs:5:1: 5:2
|
||||||
|
return; // scope 0 at $DIR/issue-78192.rs:5:2: 5:2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ async fn foo2() -> Result<(), ()> {
|
||||||
}
|
}
|
||||||
async fn foo3() -> Result<(), ()> {
|
async fn foo3() -> Result<(), ()> {
|
||||||
let _ = await bar()?; //~ ERROR incorrect use of `await`
|
let _ = await bar()?; //~ ERROR incorrect use of `await`
|
||||||
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
async fn foo21() -> Result<(), ()> {
|
async fn foo21() -> Result<(), ()> {
|
||||||
|
@ -60,9 +59,7 @@ fn foo10() -> Result<(), ()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn foo11() -> Result<(), ()> {
|
fn foo11() -> Result<(), ()> {
|
||||||
let _ = await bar()?; //~ ERROR `await` is only allowed inside `async` functions and blocks
|
let _ = await bar()?; //~ ERROR incorrect use of `await`
|
||||||
//~^ ERROR incorrect use of `await`
|
|
||||||
//~| ERROR the `?` operator can only be applied to values that implement `Try`
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn foo12() -> Result<(), ()> {
|
fn foo12() -> Result<(), ()> {
|
||||||
|
|
|
@ -17,103 +17,103 @@ LL | let _ = await bar()?;
|
||||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:21:13
|
--> $DIR/incorrect-syntax-suggestions.rs:20:13
|
||||||
|
|
|
|
||||||
LL | let _ = await { bar() };
|
LL | let _ = await { bar() };
|
||||||
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
|
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:25:13
|
--> $DIR/incorrect-syntax-suggestions.rs:24:13
|
||||||
|
|
|
|
||||||
LL | let _ = await(bar());
|
LL | let _ = await(bar());
|
||||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
|
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:29:13
|
--> $DIR/incorrect-syntax-suggestions.rs:28:13
|
||||||
|
|
|
|
||||||
LL | let _ = await { bar() }?;
|
LL | let _ = await { bar() }?;
|
||||||
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
|
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:33:14
|
--> $DIR/incorrect-syntax-suggestions.rs:32:14
|
||||||
|
|
|
|
||||||
LL | let _ = (await bar())?;
|
LL | let _ = (await bar())?;
|
||||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:37:24
|
--> $DIR/incorrect-syntax-suggestions.rs:36:24
|
||||||
|
|
|
|
||||||
LL | let _ = bar().await();
|
LL | let _ = bar().await();
|
||||||
| ^^ help: `await` is not a method call, remove the parentheses
|
| ^^ help: `await` is not a method call, remove the parentheses
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:41:24
|
--> $DIR/incorrect-syntax-suggestions.rs:40:24
|
||||||
|
|
|
|
||||||
LL | let _ = bar().await()?;
|
LL | let _ = bar().await()?;
|
||||||
| ^^ help: `await` is not a method call, remove the parentheses
|
| ^^ help: `await` is not a method call, remove the parentheses
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:53:13
|
--> $DIR/incorrect-syntax-suggestions.rs:52:13
|
||||||
|
|
|
|
||||||
LL | let _ = await bar();
|
LL | let _ = await bar();
|
||||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:58:13
|
--> $DIR/incorrect-syntax-suggestions.rs:57:13
|
||||||
|
|
|
|
||||||
LL | let _ = await? bar();
|
LL | let _ = await? bar();
|
||||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
|
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:63:13
|
--> $DIR/incorrect-syntax-suggestions.rs:62:13
|
||||||
|
|
|
|
||||||
LL | let _ = await bar()?;
|
LL | let _ = await bar()?;
|
||||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:69:14
|
--> $DIR/incorrect-syntax-suggestions.rs:66:14
|
||||||
|
|
|
|
||||||
LL | let _ = (await bar())?;
|
LL | let _ = (await bar())?;
|
||||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:74:24
|
--> $DIR/incorrect-syntax-suggestions.rs:71:24
|
||||||
|
|
|
|
||||||
LL | let _ = bar().await();
|
LL | let _ = bar().await();
|
||||||
| ^^ help: `await` is not a method call, remove the parentheses
|
| ^^ help: `await` is not a method call, remove the parentheses
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:79:24
|
--> $DIR/incorrect-syntax-suggestions.rs:76:24
|
||||||
|
|
|
|
||||||
LL | let _ = bar().await()?;
|
LL | let _ = bar().await()?;
|
||||||
| ^^ help: `await` is not a method call, remove the parentheses
|
| ^^ help: `await` is not a method call, remove the parentheses
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:107:13
|
--> $DIR/incorrect-syntax-suggestions.rs:104:13
|
||||||
|
|
|
|
||||||
LL | let _ = await!(bar());
|
LL | let _ = await!(bar());
|
||||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:111:13
|
--> $DIR/incorrect-syntax-suggestions.rs:108:13
|
||||||
|
|
|
|
||||||
LL | let _ = await!(bar())?;
|
LL | let _ = await!(bar())?;
|
||||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:116:17
|
--> $DIR/incorrect-syntax-suggestions.rs:113:17
|
||||||
|
|
|
|
||||||
LL | let _ = await!(bar())?;
|
LL | let _ = await!(bar())?;
|
||||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:124:17
|
--> $DIR/incorrect-syntax-suggestions.rs:121:17
|
||||||
|
|
|
|
||||||
LL | let _ = await!(bar())?;
|
LL | let _ = await!(bar())?;
|
||||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||||
|
|
||||||
error: expected expression, found `=>`
|
error: expected expression, found `=>`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:132:25
|
--> $DIR/incorrect-syntax-suggestions.rs:129:25
|
||||||
|
|
|
|
||||||
LL | match await { await => () }
|
LL | match await { await => () }
|
||||||
| ----- ^^ expected expression
|
| ----- ^^ expected expression
|
||||||
|
@ -121,13 +121,13 @@ LL | match await { await => () }
|
||||||
| while parsing this incorrect await expression
|
| while parsing this incorrect await expression
|
||||||
|
|
||||||
error: incorrect use of `await`
|
error: incorrect use of `await`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:132:11
|
--> $DIR/incorrect-syntax-suggestions.rs:129:11
|
||||||
|
|
|
|
||||||
LL | match await { await => () }
|
LL | match await { await => () }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
|
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
|
||||||
|
|
||||||
error: expected one of `.`, `?`, `{`, or an operator, found `}`
|
error: expected one of `.`, `?`, `{`, or an operator, found `}`
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:135:1
|
--> $DIR/incorrect-syntax-suggestions.rs:132:1
|
||||||
|
|
|
|
||||||
LL | match await { await => () }
|
LL | match await { await => () }
|
||||||
| ----- - expected one of `.`, `?`, `{`, or an operator
|
| ----- - expected one of `.`, `?`, `{`, or an operator
|
||||||
|
@ -138,7 +138,7 @@ LL | }
|
||||||
| ^ unexpected token
|
| ^ unexpected token
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:53:13
|
--> $DIR/incorrect-syntax-suggestions.rs:52:13
|
||||||
|
|
|
|
||||||
LL | fn foo9() -> Result<(), ()> {
|
LL | fn foo9() -> Result<(), ()> {
|
||||||
| ---- this is not `async`
|
| ---- this is not `async`
|
||||||
|
@ -146,7 +146,7 @@ LL | let _ = await bar();
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:58:13
|
--> $DIR/incorrect-syntax-suggestions.rs:57:13
|
||||||
|
|
|
|
||||||
LL | fn foo10() -> Result<(), ()> {
|
LL | fn foo10() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
|
@ -154,15 +154,7 @@ LL | let _ = await? bar();
|
||||||
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:63:13
|
--> $DIR/incorrect-syntax-suggestions.rs:66:14
|
||||||
|
|
|
||||||
LL | fn foo11() -> Result<(), ()> {
|
|
||||||
| ----- this is not `async`
|
|
||||||
LL | let _ = await bar()?;
|
|
||||||
| ^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:69:14
|
|
||||||
|
|
|
|
||||||
LL | fn foo12() -> Result<(), ()> {
|
LL | fn foo12() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
|
@ -170,7 +162,7 @@ LL | let _ = (await bar())?;
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:74:13
|
--> $DIR/incorrect-syntax-suggestions.rs:71:13
|
||||||
|
|
|
|
||||||
LL | fn foo13() -> Result<(), ()> {
|
LL | fn foo13() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
|
@ -178,7 +170,7 @@ LL | let _ = bar().await();
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:79:13
|
--> $DIR/incorrect-syntax-suggestions.rs:76:13
|
||||||
|
|
|
|
||||||
LL | fn foo14() -> Result<(), ()> {
|
LL | fn foo14() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
|
@ -186,7 +178,7 @@ LL | let _ = bar().await()?;
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:84:13
|
--> $DIR/incorrect-syntax-suggestions.rs:81:13
|
||||||
|
|
|
|
||||||
LL | fn foo15() -> Result<(), ()> {
|
LL | fn foo15() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
|
@ -194,7 +186,7 @@ LL | let _ = bar().await;
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:88:13
|
--> $DIR/incorrect-syntax-suggestions.rs:85:13
|
||||||
|
|
|
|
||||||
LL | fn foo16() -> Result<(), ()> {
|
LL | fn foo16() -> Result<(), ()> {
|
||||||
| ----- this is not `async`
|
| ----- this is not `async`
|
||||||
|
@ -202,7 +194,7 @@ LL | let _ = bar().await?;
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:93:17
|
--> $DIR/incorrect-syntax-suggestions.rs:90:17
|
||||||
|
|
|
|
||||||
LL | fn foo() -> Result<(), ()> {
|
LL | fn foo() -> Result<(), ()> {
|
||||||
| --- this is not `async`
|
| --- this is not `async`
|
||||||
|
@ -210,7 +202,7 @@ LL | let _ = bar().await?;
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:100:17
|
--> $DIR/incorrect-syntax-suggestions.rs:97:17
|
||||||
|
|
|
|
||||||
LL | let foo = || {
|
LL | let foo = || {
|
||||||
| -- this is not `async`
|
| -- this is not `async`
|
||||||
|
@ -218,7 +210,7 @@ LL | let _ = bar().await?;
|
||||||
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:116:17
|
--> $DIR/incorrect-syntax-suggestions.rs:113:17
|
||||||
|
|
|
|
||||||
LL | fn foo() -> Result<(), ()> {
|
LL | fn foo() -> Result<(), ()> {
|
||||||
| --- this is not `async`
|
| --- this is not `async`
|
||||||
|
@ -226,35 +218,13 @@ LL | let _ = await!(bar())?;
|
||||||
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:124:17
|
--> $DIR/incorrect-syntax-suggestions.rs:121:17
|
||||||
|
|
|
|
||||||
LL | let foo = || {
|
LL | let foo = || {
|
||||||
| -- this is not `async`
|
| -- this is not `async`
|
||||||
LL | let _ = await!(bar())?;
|
LL | let _ = await!(bar())?;
|
||||||
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||||
|
|
||||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
error: aborting due to 33 previous errors
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:16:19
|
|
||||||
|
|
|
||||||
LL | let _ = await bar()?;
|
|
||||||
| ^^^^^^
|
|
||||||
| |
|
|
||||||
| the `?` operator cannot be applied to type `impl Future`
|
|
||||||
| help: consider using `.await` here: `bar().await?`
|
|
||||||
|
|
|
||||||
= help: the trait `Try` is not implemented for `impl Future`
|
|
||||||
= note: required by `into_result`
|
|
||||||
|
|
||||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
For more information about this error, try `rustc --explain E0728`.
|
||||||
--> $DIR/incorrect-syntax-suggestions.rs:63:19
|
|
||||||
|
|
|
||||||
LL | let _ = await bar()?;
|
|
||||||
| ^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
|
||||||
|
|
|
||||||
= help: the trait `Try` is not implemented for `impl Future`
|
|
||||||
= note: required by `into_result`
|
|
||||||
|
|
||||||
error: aborting due to 36 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0728.
|
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
|
||||||
|
|
|
@ -9,6 +9,10 @@ LL | take_u32(x)
|
||||||
|
|
|
|
||||||
= note: expected type `u32`
|
= note: expected type `u32`
|
||||||
found opaque type `impl Future`
|
found opaque type `impl Future`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | take_u32(x.await)
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -2,25 +2,27 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try
|
||||||
--> $DIR/issue-61076.rs:42:5
|
--> $DIR/issue-61076.rs:42:5
|
||||||
|
|
|
|
||||||
LL | foo()?;
|
LL | foo()?;
|
||||||
| ^^^^^^
|
| ^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||||
| |
|
|
||||||
| the `?` operator cannot be applied to type `impl Future`
|
|
||||||
| help: consider using `.await` here: `foo().await?`
|
|
||||||
|
|
|
|
||||||
= help: the trait `Try` is not implemented for `impl Future`
|
= help: the trait `Try` is not implemented for `impl Future`
|
||||||
= note: required by `into_result`
|
= note: required by `into_result`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | foo().await?;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||||
--> $DIR/issue-61076.rs:56:5
|
--> $DIR/issue-61076.rs:56:5
|
||||||
|
|
|
|
||||||
LL | t?;
|
LL | t?;
|
||||||
| ^^
|
| ^^ the `?` operator cannot be applied to type `T`
|
||||||
| |
|
|
||||||
| the `?` operator cannot be applied to type `T`
|
|
||||||
| help: consider using `.await` here: `t.await?`
|
|
||||||
|
|
|
|
||||||
= help: the trait `Try` is not implemented for `T`
|
= help: the trait `Try` is not implemented for `T`
|
||||||
= note: required by `into_result`
|
= note: required by `into_result`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | t.await?;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error[E0609]: no field `0` on type `impl Future`
|
error[E0609]: no field `0` on type `impl Future`
|
||||||
--> $DIR/issue-61076.rs:58:26
|
--> $DIR/issue-61076.rs:58:26
|
||||||
|
@ -51,6 +53,10 @@ LL | Tuple(_) => {}
|
||||||
|
|
|
|
||||||
= note: expected opaque type `impl Future`
|
= note: expected opaque type `impl Future`
|
||||||
found struct `Tuple`
|
found struct `Tuple`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | match tuple().await {
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ async fn suggest_await_in_async_closure() {
|
||||||
let x = make_u32();
|
let x = make_u32();
|
||||||
take_u32(x.await)
|
take_u32(x.await)
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//~| HELP consider using `.await` here
|
//~| HELP consider `await`ing on the `Future`
|
||||||
//~| SUGGESTION x.await
|
//~| SUGGESTION .await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ async fn suggest_await_in_async_closure() {
|
||||||
let x = make_u32();
|
let x = make_u32();
|
||||||
take_u32(x)
|
take_u32(x)
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//~| HELP consider using `.await` here
|
//~| HELP consider `await`ing on the `Future`
|
||||||
//~| SUGGESTION x.await
|
//~| SUGGESTION .await
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,14 @@ LL | async fn make_u32() -> u32 {
|
||||||
| --- the `Output` of this `async fn`'s found opaque type
|
| --- the `Output` of this `async fn`'s found opaque type
|
||||||
...
|
...
|
||||||
LL | take_u32(x)
|
LL | take_u32(x)
|
||||||
| ^
|
| ^ expected `u32`, found opaque type
|
||||||
| |
|
|
||||||
| expected `u32`, found opaque type
|
|
||||||
| help: consider using `.await` here: `x.await`
|
|
||||||
|
|
|
|
||||||
= note: expected type `u32`
|
= note: expected type `u32`
|
||||||
found opaque type `impl Future`
|
found opaque type `impl Future`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | take_u32(x.await)
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// edition:2018
|
|
||||||
// run-rustfix
|
|
||||||
|
|
||||||
fn take_u32(_x: u32) {}
|
|
||||||
|
|
||||||
async fn make_u32() -> u32 {
|
|
||||||
22
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
async fn suggest_await_in_async_fn() {
|
|
||||||
let x = make_u32();
|
|
||||||
take_u32(x.await)
|
|
||||||
//~^ ERROR mismatched types [E0308]
|
|
||||||
//~| HELP consider using `.await` here
|
|
||||||
//~| SUGGESTION x.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn dummy() {}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
async fn suggest_await_in_async_fn_return() {
|
|
||||||
dummy().await;
|
|
||||||
//~^ ERROR mismatched types [E0308]
|
|
||||||
//~| HELP try adding a semicolon
|
|
||||||
//~| HELP consider using `.await` here
|
|
||||||
//~| SUGGESTION dummy().await
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +1,4 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
// run-rustfix
|
|
||||||
|
|
||||||
fn take_u32(_x: u32) {}
|
fn take_u32(_x: u32) {}
|
||||||
|
|
||||||
|
@ -12,8 +11,8 @@ async fn suggest_await_in_async_fn() {
|
||||||
let x = make_u32();
|
let x = make_u32();
|
||||||
take_u32(x)
|
take_u32(x)
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//~| HELP consider using `.await` here
|
//~| HELP consider `await`ing on the `Future`
|
||||||
//~| SUGGESTION x.await
|
//~| SUGGESTION .await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn dummy() {}
|
async fn dummy() {}
|
||||||
|
@ -23,8 +22,8 @@ async fn suggest_await_in_async_fn_return() {
|
||||||
dummy()
|
dummy()
|
||||||
//~^ ERROR mismatched types [E0308]
|
//~^ ERROR mismatched types [E0308]
|
||||||
//~| HELP try adding a semicolon
|
//~| HELP try adding a semicolon
|
||||||
//~| HELP consider using `.await` here
|
//~| HELP consider `await`ing on the `Future`
|
||||||
//~| SUGGESTION dummy().await
|
//~| SUGGESTION .await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/suggest-missing-await.rs:13:14
|
--> $DIR/suggest-missing-await.rs:12:14
|
||||||
|
|
|
|
||||||
LL | async fn make_u32() -> u32 {
|
LL | async fn make_u32() -> u32 {
|
||||||
| --- the `Output` of this `async fn`'s found opaque type
|
| --- the `Output` of this `async fn`'s found opaque type
|
||||||
...
|
...
|
||||||
LL | take_u32(x)
|
LL | take_u32(x)
|
||||||
| ^
|
| ^ expected `u32`, found opaque type
|
||||||
| |
|
|
||||||
| expected `u32`, found opaque type
|
|
||||||
| help: consider using `.await` here: `x.await`
|
|
||||||
|
|
|
|
||||||
= note: expected type `u32`
|
= note: expected type `u32`
|
||||||
found opaque type `impl Future`
|
found opaque type `impl Future`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | take_u32(x.await)
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/suggest-missing-await.rs:23:5
|
--> $DIR/suggest-missing-await.rs:22:5
|
||||||
|
|
|
|
||||||
LL | async fn dummy() {}
|
LL | async fn dummy() {}
|
||||||
| - the `Output` of this `async fn`'s found opaque type
|
| - the `Output` of this `async fn`'s found opaque type
|
||||||
|
@ -24,14 +25,14 @@ LL | dummy()
|
||||||
|
|
|
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found opaque type `impl Future`
|
found opaque type `impl Future`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | dummy().await
|
||||||
|
| ^^^^^^
|
||||||
help: try adding a semicolon
|
help: try adding a semicolon
|
||||||
|
|
|
|
||||||
LL | dummy();
|
LL | dummy();
|
||||||
| ^
|
| ^
|
||||||
help: consider using `.await` here
|
|
||||||
|
|
|
||||||
LL | dummy().await
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
35
src/test/ui/issues/issue-56229.rs
Normal file
35
src/test/ui/issues/issue-56229.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
trait Mirror {
|
||||||
|
type Other;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Even(usize);
|
||||||
|
struct Odd;
|
||||||
|
|
||||||
|
impl Mirror for Even {
|
||||||
|
type Other = Odd;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mirror for Odd {
|
||||||
|
type Other = Even;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Dyn<T: Mirror>: AsRef<<T as Mirror>::Other> {}
|
||||||
|
|
||||||
|
impl Dyn<Odd> for Even {}
|
||||||
|
|
||||||
|
impl AsRef<Even> for Even {
|
||||||
|
fn as_ref(&self) -> &Even {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code<T: Mirror>(d: &dyn Dyn<T>) -> &T::Other {
|
||||||
|
d.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("{:?}", code(&Even(22)));
|
||||||
|
}
|
23
src/test/ui/issues/issue-59494.rs
Normal file
23
src/test/ui/issues/issue-59494.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
fn t7p<A, B, C>(f: impl Fn(B) -> C, g: impl Fn(A) -> B) -> impl Fn(A) -> C {
|
||||||
|
move |a: A| -> C { f(g(a)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn t8n<A, B, C>(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C)
|
||||||
|
where
|
||||||
|
A: Copy,
|
||||||
|
{
|
||||||
|
move |a: A| -> (B, C) {
|
||||||
|
let b = a;
|
||||||
|
let fa = f(a);
|
||||||
|
let ga = g(b);
|
||||||
|
(fa, ga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f = |(_, _)| {};
|
||||||
|
let g = |(a, _)| a;
|
||||||
|
let t7 = |env| |a| |b| t7p(f, g)(((env, a), b));
|
||||||
|
let t8 = t8n(t7, t7p(f, g));
|
||||||
|
//~^ ERROR: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>
|
||||||
|
}
|
14
src/test/ui/issues/issue-59494.stderr
Normal file
14
src/test/ui/issues/issue-59494.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
|
||||||
|
--> $DIR/issue-59494.rs:21:22
|
||||||
|
|
|
||||||
|
LL | fn t8n<A, B, C>(f: impl Fn(A) -> B, g: impl Fn(A) -> C) -> impl Fn(A) -> (B, C)
|
||||||
|
| ---------- required by this bound in `t8n`
|
||||||
|
...
|
||||||
|
LL | let t8 = t8n(t7, t7p(f, g));
|
||||||
|
| ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
|
||||||
|
|
|
||||||
|
= help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
29
src/test/ui/issues/issue-70746.rs
Normal file
29
src/test/ui/issues/issue-70746.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
pub trait Trait1 {
|
||||||
|
type C;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct T1;
|
||||||
|
impl Trait1 for T1 {
|
||||||
|
type C = usize;
|
||||||
|
}
|
||||||
|
pub trait Callback<T: Trait1>: FnMut(<T as Trait1>::C) {}
|
||||||
|
impl<T: Trait1, F: FnMut(<T as Trait1>::C)> Callback<T> for F {}
|
||||||
|
|
||||||
|
pub struct State<T: Trait1> {
|
||||||
|
callback: Option<Box<dyn Callback<T>>>,
|
||||||
|
}
|
||||||
|
impl<T: Trait1> State<T> {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { callback: None }
|
||||||
|
}
|
||||||
|
fn test_cb(&mut self, d: <T as Trait1>::C) {
|
||||||
|
(self.callback.as_mut().unwrap())(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut s = State::<T1>::new();
|
||||||
|
s.test_cb(1);
|
||||||
|
}
|
33
src/test/ui/issues/issue-73229.rs
Normal file
33
src/test/ui/issues/issue-73229.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
fn any<T>() -> T {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
type V;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Callback<T: Foo>: Fn(&T, &T::V) {}
|
||||||
|
impl<T: Foo, F: Fn(&T, &T::V)> Callback<T> for F {}
|
||||||
|
|
||||||
|
struct Bar<T: Foo> {
|
||||||
|
callback: Box<dyn Callback<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Foo> Bar<T> {
|
||||||
|
fn event(&self) {
|
||||||
|
(self.callback)(any(), any());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A;
|
||||||
|
struct B;
|
||||||
|
impl Foo for A {
|
||||||
|
type V = B;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo = Bar::<A> { callback: Box::new(|_: &A, _: &B| ()) };
|
||||||
|
foo.event();
|
||||||
|
}
|
18
src/test/ui/regions/issue-78262.default.stderr
Normal file
18
src/test/ui/regions/issue-78262.default.stderr
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-78262.rs:12:28
|
||||||
|
|
|
||||||
|
LL | let f = |x: &dyn TT| x.func();
|
||||||
|
| ^^^^ lifetime mismatch
|
||||||
|
|
|
||||||
|
= note: expected reference `&(dyn TT + 'static)`
|
||||||
|
found reference `&dyn TT`
|
||||||
|
note: the anonymous lifetime #1 defined on the body at 12:13...
|
||||||
|
--> $DIR/issue-78262.rs:12:13
|
||||||
|
|
|
||||||
|
LL | let f = |x: &dyn TT| x.func();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...does not necessarily outlive the static lifetime
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
10
src/test/ui/regions/issue-78262.nll.stderr
Normal file
10
src/test/ui/regions/issue-78262.nll.stderr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
error[E0521]: borrowed data escapes outside of closure
|
||||||
|
--> $DIR/issue-78262.rs:12:26
|
||||||
|
|
|
||||||
|
LL | let f = |x: &dyn TT| x.func();
|
||||||
|
| - ^^^^^^^^ `x` escapes the closure body here
|
||||||
|
| |
|
||||||
|
| `x` is a reference that is only valid in the closure body
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
14
src/test/ui/regions/issue-78262.rs
Normal file
14
src/test/ui/regions/issue-78262.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// revisions: nll default
|
||||||
|
// ignore-compare-mode-nll
|
||||||
|
//[nll]compile-flags: -Z borrowck=mir
|
||||||
|
|
||||||
|
trait TT {}
|
||||||
|
|
||||||
|
impl dyn TT {
|
||||||
|
fn func(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f = |x: &dyn TT| x.func(); //[default]~ ERROR: mismatched types
|
||||||
|
//[nll]~^ ERROR: borrowed data escapes outside of closure
|
||||||
|
}
|
|
@ -2,13 +2,14 @@ error[E0277]: the `?` operator can only be applied to values that implement `Try
|
||||||
--> $DIR/issue-72766.rs:14:5
|
--> $DIR/issue-72766.rs:14:5
|
||||||
|
|
|
|
||||||
LL | SadGirl {}.call()?;
|
LL | SadGirl {}.call()?;
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||||
| |
|
|
||||||
| the `?` operator cannot be applied to type `impl Future`
|
|
||||||
| help: consider using `.await` here: `SadGirl {}.call().await?`
|
|
||||||
|
|
|
|
||||||
= help: the trait `Try` is not implemented for `impl Future`
|
= help: the trait `Try` is not implemented for `impl Future`
|
||||||
= note: required by `into_result`
|
= note: required by `into_result`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | SadGirl {}.call().await?;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
57
src/test/ui/suggestions/match-prev-arm-needing-semi.rs
Normal file
57
src/test/ui/suggestions/match-prev-arm-needing-semi.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
fn dummy() -> i32 { 42 }
|
||||||
|
|
||||||
|
fn extra_semicolon() {
|
||||||
|
let _ = match true { //~ NOTE `match` arms have incompatible types
|
||||||
|
true => {
|
||||||
|
dummy(); //~ NOTE this is found to be
|
||||||
|
//~^ HELP consider removing this semicolon
|
||||||
|
}
|
||||||
|
false => dummy(), //~ ERROR `match` arms have incompatible types
|
||||||
|
//~^ NOTE expected `()`, found `i32`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn async_dummy() {} //~ NOTE the `Output` of this `async fn`'s found opaque type
|
||||||
|
async fn async_dummy2() {} //~ NOTE the `Output` of this `async fn`'s found opaque type
|
||||||
|
//~^ NOTE the `Output` of this `async fn`'s found opaque type
|
||||||
|
|
||||||
|
async fn async_extra_semicolon_same() {
|
||||||
|
let _ = match true { //~ NOTE `match` arms have incompatible types
|
||||||
|
true => {
|
||||||
|
async_dummy(); //~ NOTE this is found to be
|
||||||
|
//~^ HELP consider removing this semicolon
|
||||||
|
}
|
||||||
|
false => async_dummy(), //~ ERROR `match` arms have incompatible types
|
||||||
|
//~^ NOTE expected `()`, found opaque type
|
||||||
|
//~| NOTE expected type `()`
|
||||||
|
//~| HELP consider `await`ing on the `Future`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn async_extra_semicolon_different() {
|
||||||
|
let _ = match true { //~ NOTE `match` arms have incompatible types
|
||||||
|
true => {
|
||||||
|
async_dummy(); //~ NOTE this is found to be
|
||||||
|
//~^ HELP consider removing this semicolon
|
||||||
|
}
|
||||||
|
false => async_dummy2(), //~ ERROR `match` arms have incompatible types
|
||||||
|
//~^ NOTE expected `()`, found opaque type
|
||||||
|
//~| NOTE expected type `()`
|
||||||
|
//~| HELP consider `await`ing on the `Future`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn async_different_futures() {
|
||||||
|
let _ = match true { //~ NOTE `match` arms have incompatible types
|
||||||
|
true => async_dummy(), //~ NOTE this is found to be
|
||||||
|
//~| HELP consider `await`ing on both `Future`s
|
||||||
|
false => async_dummy2(), //~ ERROR `match` arms have incompatible types
|
||||||
|
//~^ NOTE expected opaque type, found a different opaque type
|
||||||
|
//~| NOTE expected type `impl Future`
|
||||||
|
//~| NOTE distinct uses of `impl Trait` result in different opaque types
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
118
src/test/ui/suggestions/match-prev-arm-needing-semi.stderr
Normal file
118
src/test/ui/suggestions/match-prev-arm-needing-semi.stderr
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/match-prev-arm-needing-semi.rs:26:18
|
||||||
|
|
|
||||||
|
LL | async fn async_dummy() {}
|
||||||
|
| - the `Output` of this `async fn`'s found opaque type
|
||||||
|
...
|
||||||
|
LL | let _ = match true {
|
||||||
|
| _____________-
|
||||||
|
LL | | true => {
|
||||||
|
LL | | async_dummy();
|
||||||
|
| | -------------- this is found to be of type `()`
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
LL | | false => async_dummy(),
|
||||||
|
| | ^^^^^^^^^^^^^ expected `()`, found opaque type
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `()`
|
||||||
|
found opaque type `impl Future`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | false => async_dummy().await,
|
||||||
|
| ^^^^^^
|
||||||
|
help: consider removing this semicolon and boxing the expressions
|
||||||
|
|
|
||||||
|
LL | Box::new(async_dummy())
|
||||||
|
LL |
|
||||||
|
LL | }
|
||||||
|
LL | false => Box::new(async_dummy()),
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/match-prev-arm-needing-semi.rs:39:18
|
||||||
|
|
|
||||||
|
LL | async fn async_dummy2() {}
|
||||||
|
| - the `Output` of this `async fn`'s found opaque type
|
||||||
|
...
|
||||||
|
LL | let _ = match true {
|
||||||
|
| _____________-
|
||||||
|
LL | | true => {
|
||||||
|
LL | | async_dummy();
|
||||||
|
| | -------------- this is found to be of type `()`
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
LL | | false => async_dummy2(),
|
||||||
|
| | ^^^^^^^^^^^^^^ expected `()`, found opaque type
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `()`
|
||||||
|
found opaque type `impl Future`
|
||||||
|
help: consider `await`ing on the `Future`
|
||||||
|
|
|
||||||
|
LL | false => async_dummy2().await,
|
||||||
|
| ^^^^^^
|
||||||
|
help: consider removing this semicolon and boxing the expressions
|
||||||
|
|
|
||||||
|
LL | Box::new(async_dummy())
|
||||||
|
LL |
|
||||||
|
LL | }
|
||||||
|
LL | false => Box::new(async_dummy2()),
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/match-prev-arm-needing-semi.rs:50:18
|
||||||
|
|
|
||||||
|
LL | async fn async_dummy2() {}
|
||||||
|
| - the `Output` of this `async fn`'s found opaque type
|
||||||
|
...
|
||||||
|
LL | let _ = match true {
|
||||||
|
| _____________-
|
||||||
|
LL | | true => async_dummy(),
|
||||||
|
| | ------------- this is found to be of type `impl Future`
|
||||||
|
LL | |
|
||||||
|
LL | | false => async_dummy2(),
|
||||||
|
| | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
|
||||||
|
... |
|
||||||
|
LL | |
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
|
||||||
|
= note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>)
|
||||||
|
found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:17:25>)
|
||||||
|
= note: distinct uses of `impl Trait` result in different opaque types
|
||||||
|
help: consider `await`ing on both `Future`s
|
||||||
|
|
|
||||||
|
LL | true => async_dummy().await,
|
||||||
|
LL |
|
||||||
|
LL | false => async_dummy2().await,
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0308]: `match` arms have incompatible types
|
||||||
|
--> $DIR/match-prev-arm-needing-semi.rs:11:18
|
||||||
|
|
|
||||||
|
LL | let _ = match true {
|
||||||
|
| _____________-
|
||||||
|
LL | | true => {
|
||||||
|
LL | | dummy();
|
||||||
|
| | --------
|
||||||
|
| | | |
|
||||||
|
| | | help: consider removing this semicolon
|
||||||
|
| | this is found to be of type `()`
|
||||||
|
LL | |
|
||||||
|
LL | | }
|
||||||
|
LL | | false => dummy(),
|
||||||
|
| | ^^^^^^^ expected `()`, found `i32`
|
||||||
|
LL | |
|
||||||
|
LL | | };
|
||||||
|
| |_____- `match` arms have incompatible types
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -16,6 +16,12 @@ LL | | }.await
|
||||||
= note: expected type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
|
= note: expected type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:8:19>)
|
||||||
found opaque type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
|
found opaque type `impl Future` (opaque type at <$DIR/opaque-type-error.rs:12:19>)
|
||||||
= note: distinct uses of `impl Trait` result in different opaque types
|
= note: distinct uses of `impl Trait` result in different opaque types
|
||||||
|
help: consider `await`ing on both `Future`s
|
||||||
|
|
|
||||||
|
LL | thing_one().await
|
||||||
|
LL | } else {
|
||||||
|
LL | thing_two().await
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
diff = "0.1.10"
|
diff = "0.1.10"
|
||||||
env_logger = { version = "0.7", default-features = false }
|
|
||||||
getopts = "0.2"
|
getopts = "0.2"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.2.13", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub mod runtest;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let config = parse_config(env::args().collect());
|
let config = parse_config(env::args().collect());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue