mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-02 18:12:51 +00:00
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
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Rust Programming Language Forum
|
||||
- name: Question
|
||||
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"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"env_logger 0.7.1",
|
||||
"getopts",
|
||||
"glob",
|
||||
"lazy_static",
|
||||
@ -660,6 +659,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"walkdir",
|
||||
"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.
|
||||
let target = &bx.cx.tcx.sess.target;
|
||||
let arch = &bx.cx.tcx.sess.target.arch;
|
||||
match (&**arch, target.options.is_like_windows) {
|
||||
match &**arch {
|
||||
// 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)
|
||||
}
|
||||
// Generic x86
|
||||
("x86", _) => {
|
||||
emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true)
|
||||
}
|
||||
"x86" => emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true),
|
||||
// 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)
|
||||
}
|
||||
// iOS AArch64
|
||||
("aarch64", _) if target.target_os == "ios" => {
|
||||
// macOS / iOS AArch64
|
||||
"aarch64" if target.options.is_like_osx => {
|
||||
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
|
||||
("x86_64", true) => {
|
||||
"x86_64" if target.options.is_like_windows => {
|
||||
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();
|
||||
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 crate::infer;
|
||||
use crate::infer::OriginalQueryValues;
|
||||
use crate::traits::error_reporting::report_object_safety_error;
|
||||
use crate::traits::{
|
||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||
StatementAsExpression,
|
||||
};
|
||||
|
||||
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::{Item, ItemKind, Node};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::ParamEnvAnd;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
subst::{Subst, SubstsRef},
|
||||
@ -688,13 +687,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
};
|
||||
let msg = "`match` arms have incompatible types";
|
||||
err.span_label(outer_error_span, msg);
|
||||
if let Some(sp) = semi_span {
|
||||
err.span_suggestion_short(
|
||||
sp,
|
||||
"consider removing this semicolon",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if let Some((sp, boxed)) = semi_span {
|
||||
if let (StatementAsExpression::NeedsBoxing, [.., prior_arm]) =
|
||||
(boxed, &prior_arms[..])
|
||||
{
|
||||
err.multipart_suggestion(
|
||||
"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 {
|
||||
// Get return type span and point to it.
|
||||
@ -717,13 +739,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
if let Some(sp) = outer {
|
||||
err.span_label(sp, "`if` and `else` have incompatible types");
|
||||
}
|
||||
if let Some(sp) = semicolon {
|
||||
err.span_suggestion_short(
|
||||
sp,
|
||||
"consider removing this semicolon",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if let Some((sp, boxed)) = semicolon {
|
||||
if matches!(boxed, StatementAsExpression::NeedsBoxing) {
|
||||
err.multipart_suggestion(
|
||||
"consider removing this semicolon and boxing the expression",
|
||||
vec![
|
||||
(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 {
|
||||
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::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 {
|
||||
self.suggest_as_ref_where_appropriate(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);
|
||||
}
|
||||
|
||||
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 ty::Opaque(def_id, _) = *exp_found.expected.kind() {
|
||||
fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
|
||||
if let ty::Opaque(def_id, substs) = ty.kind() {
|
||||
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
|
||||
// Future::Output
|
||||
let item_def_id = self
|
||||
@ -1646,37 +1681,121 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
.unwrap()
|
||||
.def_id;
|
||||
|
||||
let projection_ty = self.tcx.projection_ty_from_predicates((def_id, item_def_id));
|
||||
if let Some(projection_ty) = projection_ty {
|
||||
let projection_query = self.canonicalize_query(
|
||||
&ParamEnvAnd { param_env: self.tcx.param_env(def_id), value: projection_ty },
|
||||
&mut OriginalQueryValues::default(),
|
||||
);
|
||||
if let Ok(resp) = self.tcx.normalize_projection_ty(projection_query) {
|
||||
let normalized_ty = resp.value.value.normalized_ty;
|
||||
debug!("suggest_await_on_expect_found: normalized={:?}", normalized_ty);
|
||||
if ty::TyS::same_type(normalized_ty, exp_found.found) {
|
||||
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,
|
||||
);
|
||||
let bounds = self.tcx.explicit_item_bounds(*def_id);
|
||||
|
||||
for (predicate, _) in bounds {
|
||||
let predicate = predicate.subst(self.tcx, substs);
|
||||
if let ty::PredicateAtom::Projection(projection_predicate) =
|
||||
predicate.skip_binders()
|
||||
{
|
||||
if projection_predicate.projection_ty.item_def_id == item_def_id {
|
||||
// We don't account for multiple `Future::Output = Ty` contraints.
|
||||
return Some(projection_predicate.ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
@ -39,6 +39,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
) if **sub_r == RegionKind::ReStatic => {
|
||||
// This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
|
||||
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 lifetime = if sup_r.has_name() {
|
||||
format!("lifetime `{}`", sup_r)
|
||||
|
@ -340,11 +340,24 @@ impl ObligationCauseCode<'_> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
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)]
|
||||
pub struct MatchExpressionArmCause<'tcx> {
|
||||
pub arm_span: Span,
|
||||
pub scrut_span: Span,
|
||||
pub semi_span: Option<Span>,
|
||||
pub semi_span: Option<(Span, StatementAsExpression)>,
|
||||
pub source: hir::MatchSource,
|
||||
pub prior_arms: Vec<Span>,
|
||||
pub last_ty: Ty<'tcx>,
|
||||
@ -357,7 +370,7 @@ pub struct IfExpressionCause {
|
||||
pub then: Span,
|
||||
pub else_sp: Span,
|
||||
pub outer: Option<Span>,
|
||||
pub semicolon: Option<Span>,
|
||||
pub semicolon: Option<(Span, StatementAsExpression)>,
|
||||
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);
|
||||
match err {
|
||||
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()) {
|
||||
(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(_))) => {
|
||||
if let Ok(
|
||||
// Issue #53280
|
||||
@ -382,12 +371,12 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
db.note(
|
||||
"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(
|
||||
"for more information, visit \
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
||||
#traits-as-parameters",
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
||||
#traits-as-parameters",
|
||||
);
|
||||
}
|
||||
(ty::Projection(_), ty::Projection(_)) => {
|
||||
@ -471,8 +460,8 @@ impl<T> Trait<T> for X {
|
||||
}
|
||||
db.note(
|
||||
"for more information, visit \
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
||||
#traits-as-parameters",
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html\
|
||||
#traits-as-parameters",
|
||||
);
|
||||
}
|
||||
(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<()> {
|
||||
// FIXME(#78192): This optimization can result in unsoundness.
|
||||
if !self.tcx.sess.opts.debugging_opts.unsound_mir_opts {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Look for the sequence
|
||||
//
|
||||
// _2 = &_1;
|
||||
@ -137,6 +132,8 @@ impl OptimizationFinder<'b, 'tcx> {
|
||||
_ => None,
|
||||
}?;
|
||||
|
||||
let mut dead_locals_seen = vec![];
|
||||
|
||||
let stmt_index = location.statement_index;
|
||||
// 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
|
||||
@ -160,6 +157,11 @@ impl OptimizationFinder<'b, 'tcx> {
|
||||
BorrowKind::Shared,
|
||||
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
|
||||
.unneeded_deref
|
||||
.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.
|
||||
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.
|
||||
rustc_middle::mir::StatementKind::Assign(box (_, _))
|
||||
| rustc_middle::mir::StatementKind::Coverage(_)
|
||||
| rustc_middle::mir::StatementKind::Nop
|
||||
| rustc_middle::mir::StatementKind::FakeRead(_, _)
|
||||
| rustc_middle::mir::StatementKind::StorageLive(_)
|
||||
| rustc_middle::mir::StatementKind::StorageDead(_)
|
||||
| rustc_middle::mir::StatementKind::Retag(_, _)
|
||||
| rustc_middle::mir::StatementKind::AscribeUserType(_, _)
|
||||
| rustc_middle::mir::StatementKind::SetDiscriminant { .. } => {
|
||||
|
@ -1207,7 +1207,13 @@ impl<'a> Parser<'a> {
|
||||
self.recover_await_prefix(await_sp)?
|
||||
};
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ use rustc_middle::ty::{
|
||||
};
|
||||
use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
||||
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 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 let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||
if snippet.ends_with('?') {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"consider using `.await` here",
|
||||
format!("{}.await?", snippet.trim_end_matches('?')),
|
||||
err.span_suggestion_verbose(
|
||||
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
|
||||
"consider `await`ing on the `Future`",
|
||||
".await".to_string(),
|
||||
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::{
|
||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||
StatementAsExpression,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
@ -188,11 +189,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let (arm_span, semi_span) = if let hir::ExprKind::Block(blk, _) = &arm.body.kind {
|
||||
self.find_block_span(blk, prior_arm_ty)
|
||||
} else {
|
||||
(arm.body.span, None)
|
||||
};
|
||||
let (arm_span, semi_span) =
|
||||
self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty);
|
||||
let (span, code) = match i {
|
||||
// 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.
|
||||
@ -242,6 +240,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
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,
|
||||
/// warn the user about the match arms being unreachable.
|
||||
fn warn_arms_when_scrutinee_diverges(
|
||||
@ -514,7 +534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
block: &'tcx hir::Block<'tcx>,
|
||||
expected_ty: Option<Ty<'tcx>>,
|
||||
) -> (Span, Option<Span>) {
|
||||
) -> (Span, Option<(Span, StatementAsExpression)>) {
|
||||
if let Some(expr) = &block.expr {
|
||||
(expr.span, None)
|
||||
} else if let Some(stmt) = block.stmts.last() {
|
||||
|
@ -33,7 +33,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
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.note_need_for_fn_pointer(err, 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::opaque_types::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::slice;
|
||||
@ -1061,7 +1063,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
blk: &'tcx hir::Block<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) -> Option<Span> {
|
||||
) -> Option<(Span, StatementAsExpression)> {
|
||||
// Be helpful when the user wrote `{... expr;}` and
|
||||
// taking the `;` off is enough to fix the error.
|
||||
let last_stmt = blk.stmts.last()?;
|
||||
@ -1070,13 +1072,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
_ => return None,
|
||||
};
|
||||
let last_expr_ty = self.node_ty(last_expr.hir_id);
|
||||
if matches!(last_expr_ty.kind(), ty::Error(_))
|
||||
|| self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err()
|
||||
let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
|
||||
(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;
|
||||
}
|
||||
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
|
||||
|
@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
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::slice;
|
||||
@ -758,13 +758,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected_ty: Ty<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
) {
|
||||
if let Some(span_semi) = self.could_remove_semicolon(blk, expected_ty) {
|
||||
err.span_suggestion(
|
||||
span_semi,
|
||||
"consider removing this semicolon",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
|
||||
if let StatementAsExpression::NeedsBoxing = boxed {
|
||||
err.span_suggestion_verbose(
|
||||
span_semi,
|
||||
"consider removing this semicolon and boxing the expression",
|
||||
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_span::{self, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
@ -13,7 +12,6 @@ use rustc_hir::{ExprKind, ItemKind, Node};
|
||||
use rustc_infer::infer;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
|
||||
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(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
|
@ -62,7 +62,7 @@ impl fmt::Debug for c_void {
|
||||
// The name is WIP, using `VaListImpl` for now.
|
||||
#[cfg(any(
|
||||
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 = "asmjs",
|
||||
windows
|
||||
@ -85,7 +85,7 @@ pub struct VaListImpl<'f> {
|
||||
|
||||
#[cfg(any(
|
||||
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 = "asmjs",
|
||||
windows
|
||||
@ -107,7 +107,11 @@ impl<'f> fmt::Debug for VaListImpl<'f> {
|
||||
///
|
||||
/// [AArch64 Procedure Call Standard]:
|
||||
/// 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)]
|
||||
#[derive(Debug)]
|
||||
#[unstable(
|
||||
@ -181,7 +185,7 @@ pub struct VaList<'a, 'f: 'a> {
|
||||
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 = "asmjs",
|
||||
windows
|
||||
@ -190,7 +194,7 @@ pub struct VaList<'a, 'f: 'a> {
|
||||
|
||||
#[cfg(all(
|
||||
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 = "asmjs"),
|
||||
not(windows)
|
||||
@ -202,7 +206,7 @@ pub struct VaList<'a, 'f: 'a> {
|
||||
|
||||
#[cfg(any(
|
||||
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 = "asmjs",
|
||||
windows
|
||||
@ -223,7 +227,7 @@ impl<'f> VaListImpl<'f> {
|
||||
|
||||
#[cfg(all(
|
||||
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 = "asmjs"),
|
||||
not(windows)
|
||||
|
@ -884,10 +884,10 @@ pub fn drop<T>(_x: T) {}
|
||||
/// Interprets `src` as having type `&U`, and then reads `src` without moving
|
||||
/// the contained value.
|
||||
///
|
||||
/// This function will unsafely assume the pointer `src` is valid for
|
||||
/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading
|
||||
/// the `&U`. It will also unsafely create a copy of the contained value instead of
|
||||
/// moving out of `src`.
|
||||
/// This function will unsafely assume the pointer `src` is valid for [`size_of::<U>`][size_of]
|
||||
/// bytes by transmuting `&T` to `&U` and then reading the `&U` (except that this is done in a way
|
||||
/// that is correct even when `&U` makes stricter alignment requirements than `&T`). It will also
|
||||
/// 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
|
||||
/// 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 {
|
||||
#[inline]
|
||||
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();
|
||||
DLMALLOC.malloc(layout.size(), layout.align())
|
||||
unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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();
|
||||
DLMALLOC.calloc(layout.size(), layout.align())
|
||||
unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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();
|
||||
DLMALLOC.free(ptr, layout.size(), layout.align())
|
||||
unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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();
|
||||
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) {
|
||||
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]
|
||||
pub unsafe fn notify_all(&self) {
|
||||
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) {
|
||||
|
@ -14,6 +14,8 @@
|
||||
//! compiling for wasm. That way it's a compile time error for something that's
|
||||
//! guaranteed to be a runtime error!
|
||||
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
pub mod alloc;
|
||||
pub mod args;
|
||||
#[path = "../unsupported/cmath.rs"]
|
||||
|
@ -28,11 +28,14 @@ impl Mutex {
|
||||
|
||||
pub unsafe fn lock(&self) {
|
||||
while !self.try_lock() {
|
||||
let val = wasm32::memory_atomic_wait32(
|
||||
self.ptr(),
|
||||
1, // we expect our mutex is locked
|
||||
-1, // wait infinitely
|
||||
);
|
||||
// SAFETY: the caller must uphold the safety contract for `memory_atomic_wait32`.
|
||||
let val = unsafe {
|
||||
wasm32::memory_atomic_wait32(
|
||||
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
|
||||
// race (1). We should never time out (2)
|
||||
debug_assert!(val == 0 || val == 1);
|
||||
@ -93,19 +96,20 @@ impl ReentrantMutex {
|
||||
pub unsafe fn lock(&self) {
|
||||
let me = thread::my_id();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
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) {
|
||||
// we transitioned from unlocked to locked
|
||||
Ok(_) => {
|
||||
@ -132,7 +136,10 @@ impl ReentrantMutex {
|
||||
match *self.recursions.get() {
|
||||
0 => {
|
||||
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,
|
||||
}
|
||||
|
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
|
||||
// + 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
|
||||
- _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
|
||||
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
|
||||
|
@ -19,7 +19,7 @@
|
||||
// + 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])) }
|
||||
_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(_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
|
||||
|
@ -1,4 +1,4 @@
|
||||
// compile-flags: -O -Zunsound-mir-opts
|
||||
// compile-flags: -O
|
||||
// EMIT_MIR inst_combine_deref.simple_opt.InstCombine.diff
|
||||
fn simple_opt() -> u64 {
|
||||
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<(), ()> {
|
||||
let _ = await bar()?; //~ ERROR incorrect use of `await`
|
||||
//~^ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
Ok(())
|
||||
}
|
||||
async fn foo21() -> Result<(), ()> {
|
||||
@ -60,9 +59,7 @@ fn foo10() -> Result<(), ()> {
|
||||
Ok(())
|
||||
}
|
||||
fn foo11() -> Result<(), ()> {
|
||||
let _ = await bar()?; //~ ERROR `await` is only allowed inside `async` functions and blocks
|
||||
//~^ ERROR incorrect use of `await`
|
||||
//~| ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
let _ = await bar()?; //~ ERROR incorrect use of `await`
|
||||
Ok(())
|
||||
}
|
||||
fn foo12() -> Result<(), ()> {
|
||||
|
@ -17,103 +17,103 @@ LL | let _ = await bar()?;
|
||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:21:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:20:13
|
||||
|
|
||||
LL | let _ = await { bar() };
|
||||
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:25:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:24:13
|
||||
|
|
||||
LL | let _ = await(bar());
|
||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:29:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:28:13
|
||||
|
|
||||
LL | let _ = await { bar() }?;
|
||||
| ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:33:14
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:32:14
|
||||
|
|
||||
LL | let _ = (await bar())?;
|
||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:37:24
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:36:24
|
||||
|
|
||||
LL | let _ = bar().await();
|
||||
| ^^ help: `await` is not a method call, remove the parentheses
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:41:24
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:40:24
|
||||
|
|
||||
LL | let _ = bar().await()?;
|
||||
| ^^ help: `await` is not a method call, remove the parentheses
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:53:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:52:13
|
||||
|
|
||||
LL | let _ = await bar();
|
||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:58:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:57:13
|
||||
|
|
||||
LL | let _ = await? bar();
|
||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:63:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:62:13
|
||||
|
|
||||
LL | let _ = await bar()?;
|
||||
| ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:69:14
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:66:14
|
||||
|
|
||||
LL | let _ = (await bar())?;
|
||||
| ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:74:24
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:71:24
|
||||
|
|
||||
LL | let _ = bar().await();
|
||||
| ^^ help: `await` is not a method call, remove the parentheses
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:79:24
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:76:24
|
||||
|
|
||||
LL | let _ = bar().await()?;
|
||||
| ^^ help: `await` is not a method call, remove the parentheses
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:107:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:104:13
|
||||
|
|
||||
LL | let _ = await!(bar());
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:111:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:108:13
|
||||
|
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:116:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:113:17
|
||||
|
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:124:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:121:17
|
||||
|
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await`
|
||||
|
||||
error: expected expression, found `=>`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:132:25
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:129:25
|
||||
|
|
||||
LL | match await { await => () }
|
||||
| ----- ^^ expected expression
|
||||
@ -121,13 +121,13 @@ LL | match await { await => () }
|
||||
| while parsing this incorrect await expression
|
||||
|
||||
error: incorrect use of `await`
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:132:11
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:129:11
|
||||
|
|
||||
LL | match await { await => () }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await`
|
||||
|
||||
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 => () }
|
||||
| ----- - expected one of `.`, `?`, `{`, or an operator
|
||||
@ -138,7 +138,7 @@ LL | }
|
||||
| ^ unexpected token
|
||||
|
||||
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<(), ()> {
|
||||
| ---- this is not `async`
|
||||
@ -146,7 +146,7 @@ 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:58:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:57:13
|
||||
|
|
||||
LL | fn foo10() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -154,15 +154,7 @@ 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:63:13
|
||||
|
|
||||
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
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:66:14
|
||||
|
|
||||
LL | fn foo12() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -170,7 +162,7 @@ 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:74:13
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:71:13
|
||||
|
|
||||
LL | fn foo13() -> Result<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -178,7 +170,7 @@ LL | let _ = bar().await();
|
||||
| ^^^^^^^^^^^ 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<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -186,7 +178,7 @@ LL | let _ = bar().await()?;
|
||||
| ^^^^^^^^^^^ 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<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -194,7 +186,7 @@ LL | let _ = bar().await;
|
||||
| ^^^^^^^^^^^ 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<(), ()> {
|
||||
| ----- this is not `async`
|
||||
@ -202,7 +194,7 @@ LL | let _ = bar().await?;
|
||||
| ^^^^^^^^^^^ 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<(), ()> {
|
||||
| --- this is not `async`
|
||||
@ -210,7 +202,7 @@ LL | let _ = bar().await?;
|
||||
| ^^^^^^^^^^^ 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 = || {
|
||||
| -- this is not `async`
|
||||
@ -218,7 +210,7 @@ LL | let _ = bar().await?;
|
||||
| ^^^^^^^^^^^ 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<(), ()> {
|
||||
| --- this is not `async`
|
||||
@ -226,35 +218,13 @@ 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:124:17
|
||||
--> $DIR/incorrect-syntax-suggestions.rs:121:17
|
||||
|
|
||||
LL | let foo = || {
|
||||
| -- this is not `async`
|
||||
LL | let _ = await!(bar())?;
|
||||
| ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
|
||||
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $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: aborting due to 33 previous errors
|
||||
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $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`.
|
||||
For more information about this error, try `rustc --explain E0728`.
|
||||
|
@ -9,6 +9,10 @@ LL | take_u32(x)
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found opaque type `impl Future`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | take_u32(x.await)
|
||||
| ^^^^^^
|
||||
|
||||
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
|
||||
|
|
||||
LL | foo()?;
|
||||
| ^^^^^^
|
||||
| |
|
||||
| the `?` operator cannot be applied to type `impl Future`
|
||||
| help: consider using `.await` here: `foo().await?`
|
||||
| ^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future`
|
||||
= 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`
|
||||
--> $DIR/issue-61076.rs:56:5
|
||||
|
|
||||
LL | t?;
|
||||
| ^^
|
||||
| |
|
||||
| the `?` operator cannot be applied to type `T`
|
||||
| help: consider using `.await` here: `t.await?`
|
||||
| ^^ the `?` operator cannot be applied to type `T`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `T`
|
||||
= note: required by `into_result`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | t.await?;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0609]: no field `0` on type `impl Future`
|
||||
--> $DIR/issue-61076.rs:58:26
|
||||
@ -51,6 +53,10 @@ LL | Tuple(_) => {}
|
||||
|
|
||||
= note: expected opaque type `impl Future`
|
||||
found struct `Tuple`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | match tuple().await {
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
@ -15,8 +15,8 @@ async fn suggest_await_in_async_closure() {
|
||||
let x = make_u32();
|
||||
take_u32(x.await)
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| HELP consider using `.await` here
|
||||
//~| SUGGESTION x.await
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| SUGGESTION .await
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,8 @@ async fn suggest_await_in_async_closure() {
|
||||
let x = make_u32();
|
||||
take_u32(x)
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| HELP consider using `.await` here
|
||||
//~| SUGGESTION x.await
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| SUGGESTION .await
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,14 @@ LL | async fn make_u32() -> u32 {
|
||||
| --- the `Output` of this `async fn`'s found opaque type
|
||||
...
|
||||
LL | take_u32(x)
|
||||
| ^
|
||||
| |
|
||||
| expected `u32`, found opaque type
|
||||
| help: consider using `.await` here: `x.await`
|
||||
| ^ expected `u32`, found opaque type
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found opaque type `impl Future`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | take_u32(x.await)
|
||||
| ^^^^^^
|
||||
|
||||
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
|
||||
// run-rustfix
|
||||
|
||||
fn take_u32(_x: u32) {}
|
||||
|
||||
@ -12,8 +11,8 @@ async fn suggest_await_in_async_fn() {
|
||||
let x = make_u32();
|
||||
take_u32(x)
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| HELP consider using `.await` here
|
||||
//~| SUGGESTION x.await
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| SUGGESTION .await
|
||||
}
|
||||
|
||||
async fn dummy() {}
|
||||
@ -23,8 +22,8 @@ async fn suggest_await_in_async_fn_return() {
|
||||
dummy()
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| HELP try adding a semicolon
|
||||
//~| HELP consider using `.await` here
|
||||
//~| SUGGESTION dummy().await
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| SUGGESTION .await
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,20 +1,21 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:13:14
|
||||
--> $DIR/suggest-missing-await.rs:12:14
|
||||
|
|
||||
LL | async fn make_u32() -> u32 {
|
||||
| --- the `Output` of this `async fn`'s found opaque type
|
||||
...
|
||||
LL | take_u32(x)
|
||||
| ^
|
||||
| |
|
||||
| expected `u32`, found opaque type
|
||||
| help: consider using `.await` here: `x.await`
|
||||
| ^ expected `u32`, found opaque type
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found opaque type `impl Future`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | take_u32(x.await)
|
||||
| ^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-missing-await.rs:23:5
|
||||
--> $DIR/suggest-missing-await.rs:22:5
|
||||
|
|
||||
LL | async fn dummy() {}
|
||||
| - the `Output` of this `async fn`'s found opaque type
|
||||
@ -24,14 +25,14 @@ LL | dummy()
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found opaque type `impl Future`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | dummy().await
|
||||
| ^^^^^^
|
||||
help: try adding a semicolon
|
||||
|
|
||||
LL | dummy();
|
||||
| ^
|
||||
help: consider using `.await` here
|
||||
|
|
||||
LL | dummy().await
|
||||
|
|
||||
|
||||
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
|
||||
|
|
||||
LL | SadGirl {}.call()?;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| the `?` operator cannot be applied to type `impl Future`
|
||||
| help: consider using `.await` here: `SadGirl {}.call().await?`
|
||||
| ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future`
|
||||
= note: required by `into_result`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | SadGirl {}.call().await?;
|
||||
| ^^^^^^
|
||||
|
||||
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>)
|
||||
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
|
||||
help: consider `await`ing on both `Future`s
|
||||
|
|
||||
LL | thing_one().await
|
||||
LL | } else {
|
||||
LL | thing_two().await
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,9 +6,9 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
diff = "0.1.10"
|
||||
env_logger = { version = "0.7", default-features = false }
|
||||
getopts = "0.2"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.2.13", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
||||
regex = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
@ -35,7 +35,7 @@ pub mod runtest;
|
||||
pub mod util;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
let config = parse_config(env::args().collect());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user