mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-24 05:33:41 +00:00
Auto merge of #111342 - Dylan-DPC:rollup-b5p6wzy, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #110297 (Make `(try_)subst_and_normalize_erasing_regions` take `EarlyBinder`) - #110827 (Fix lifetime suggestion for type aliases with objects in them) - #111022 (Use smaller ints for bitflags) - #111056 (Fix some suggestions where a `Box<T>` is expected.) - #111262 (Further normalize msvc-non-utf8-ouput) - #111265 (Make generics_of has_self on RPITITs delegate to the opaque) - #111323 (Give a more helpful error when running the rustc shim directly) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c86e7fb60f
@ -845,7 +845,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some((alias_tys, alias_span)) = self
|
||||
let Some((alias_tys, alias_span, lt_addition_span)) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id) else { return; };
|
||||
@ -858,10 +858,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
()
|
||||
}
|
||||
if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
|
||||
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
|
||||
if lt.ident.name == kw::Empty {
|
||||
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
|
||||
} else {
|
||||
spans_suggs.push((lt.ident.span, "'a".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
|
||||
|
||||
if let Some(lt_addition_span) = lt_addition_span {
|
||||
spans_suggs.push((lt_addition_span, "'a, ".to_string()));
|
||||
} else {
|
||||
spans_suggs.push((alias_span.shrink_to_hi(), "<'a>".to_string()));
|
||||
}
|
||||
|
||||
diag.multipart_suggestion_verbose(
|
||||
format!(
|
||||
"to declare that the trait object {captures}, you can add a lifetime parameter `'a` in the type alias"
|
||||
|
@ -361,7 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
||||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
value,
|
||||
ty::EarlyBinder(value),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
let callee = cx.tcx.subst_and_normalize_erasing_regions(
|
||||
instance.substs,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
callee,
|
||||
ty::EarlyBinder(callee),
|
||||
);
|
||||
let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
|
||||
cx.dbg_scope_fn(callee, callee_fn_abi, None)
|
||||
|
@ -529,7 +529,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
|
||||
instance.substs,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
cx.tcx.type_of(impl_def_id).skip_binder(),
|
||||
cx.tcx.type_of(impl_def_id),
|
||||
);
|
||||
|
||||
// Only "class" methods are generally understood by LLVM,
|
||||
|
@ -111,7 +111,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.cx.tcx(),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
value,
|
||||
ty::EarlyBinder(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +495,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
) -> Result<T, InterpError<'tcx>> {
|
||||
frame
|
||||
.instance
|
||||
.try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
|
||||
.try_subst_mir_and_normalize_erasing_regions(
|
||||
*self.tcx,
|
||||
self.param_env,
|
||||
ty::EarlyBinder(value),
|
||||
)
|
||||
.map_err(|_| err_inval!(TooGeneric))
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ use parking_lot::RwLock;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct EventFilter: u32 {
|
||||
struct EventFilter: u16 {
|
||||
const GENERIC_ACTIVITIES = 1 << 0;
|
||||
const QUERY_PROVIDERS = 1 << 1;
|
||||
const QUERY_CACHE_HITS = 1 << 2;
|
||||
|
@ -75,3 +75,7 @@ hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns
|
||||
|
||||
hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but rustc had trouble determining where
|
||||
.note = we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new
|
||||
|
||||
hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||
|
||||
hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
|
||||
|
@ -51,7 +51,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|| self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
|
||||
|| self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
|
||||
|| self.suggest_no_capture_closure(err, expected, expr_ty)
|
||||
|| self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
|
||||
|| self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
|
||||
|| self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
|
||||
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
|
||||
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|
||||
|
@ -267,3 +267,31 @@ pub struct ArgMismatchIndeterminate {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum SuggestBoxing {
|
||||
#[note(hir_typeck_suggest_boxing_note)]
|
||||
#[multipart_suggestion(
|
||||
hir_typeck_suggest_boxing_when_appropriate,
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Unit {
|
||||
#[suggestion_part(code = "Box::new(())")]
|
||||
start: Span,
|
||||
#[suggestion_part(code = "")]
|
||||
end: Span,
|
||||
},
|
||||
#[note(hir_typeck_suggest_boxing_note)]
|
||||
AsyncBody,
|
||||
#[note(hir_typeck_suggest_boxing_note)]
|
||||
#[multipart_suggestion(
|
||||
hir_typeck_suggest_boxing_when_appropriate,
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Other {
|
||||
#[suggestion_part(code = "Box::new(")]
|
||||
start: Span,
|
||||
#[suggestion_part(code = ")")]
|
||||
end: Span,
|
||||
},
|
||||
}
|
||||
|
@ -1519,7 +1519,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// case we can ignore the tail expression (e.g., `'a: {
|
||||
// break 'a 22; }` would not force the type of the block
|
||||
// to be `()`).
|
||||
let tail_expr = blk.expr.as_ref();
|
||||
let coerce_to_ty = expected.coercion_target_type(self, blk.span);
|
||||
let coerce = if blk.targeted_by_break {
|
||||
CoerceMany::new(coerce_to_ty)
|
||||
@ -1537,13 +1536,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// check the tail expression **without** holding the
|
||||
// `enclosing_breakables` lock below.
|
||||
let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
|
||||
let tail_expr_ty =
|
||||
blk.expr.map(|expr| (expr, self.check_expr_with_expectation(expr, expected)));
|
||||
|
||||
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
|
||||
let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
|
||||
let coerce = ctxt.coerce.as_mut().unwrap();
|
||||
if let Some(tail_expr_ty) = tail_expr_ty {
|
||||
let tail_expr = tail_expr.unwrap();
|
||||
if let Some((tail_expr, tail_expr_ty)) = tail_expr_ty {
|
||||
let span = self.get_expr_coercion_span(tail_expr);
|
||||
let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
|
||||
let ty_for_diagnostic = coerce.merged_ty();
|
||||
@ -1596,6 +1595,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self.misc(sp),
|
||||
&mut |err| {
|
||||
if let Some(expected_ty) = expected.only_has_type(self) {
|
||||
if blk.stmts.is_empty() && blk.expr.is_none() {
|
||||
self.suggest_boxing_when_appropriate(
|
||||
err,
|
||||
blk.span,
|
||||
blk.hir_id,
|
||||
expected_ty,
|
||||
self.tcx.mk_unit(),
|
||||
);
|
||||
}
|
||||
if !self.consider_removing_semicolon(blk, expected_ty, err) {
|
||||
self.err_ctxt().consider_returning_binding(
|
||||
blk,
|
||||
@ -1608,7 +1616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// silence this redundant error, as we already emit E0070.
|
||||
|
||||
// Our block must be a `assign desugar local; assignment`
|
||||
if let Some(hir::Node::Block(hir::Block {
|
||||
if let hir::Block {
|
||||
stmts:
|
||||
[
|
||||
hir::Stmt {
|
||||
@ -1630,7 +1638,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
},
|
||||
],
|
||||
..
|
||||
})) = self.tcx.hir().find(blk.hir_id)
|
||||
} = blk
|
||||
{
|
||||
self.comes_from_while_condition(blk.hir_id, |_| {
|
||||
err.downgrade_to_delayed_bug();
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::FnCtxt;
|
||||
|
||||
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
|
||||
use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel, SuggestBoxing};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
|
||||
@ -9,7 +9,8 @@ use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
|
||||
AsyncGeneratorKind, Expr, ExprKind, GeneratorKind, GenericBound, HirId, Node, Path, QPath,
|
||||
Stmt, StmtKind, TyKind, WherePredicate,
|
||||
};
|
||||
use rustc_hir_analysis::astconv::AstConv;
|
||||
use rustc_infer::traits::{self, StatementAsExpression};
|
||||
@ -438,33 +439,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub(in super::super) fn suggest_boxing_when_appropriate(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
span: Span,
|
||||
hir_id: HirId,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) -> bool {
|
||||
if self.tcx.hir().is_inside_const_context(expr.hir_id) {
|
||||
// Do not suggest `Box::new` in const context.
|
||||
// Do not suggest `Box::new` in const context.
|
||||
if self.tcx.hir().is_inside_const_context(hir_id) || !expected.is_box() || found.is_box() {
|
||||
return false;
|
||||
}
|
||||
if !expected.is_box() || found.is_box() {
|
||||
return false;
|
||||
}
|
||||
let boxed_found = self.tcx.mk_box(found);
|
||||
if self.can_coerce(boxed_found, expected) {
|
||||
err.multipart_suggestion(
|
||||
"store this in the heap by calling `Box::new`",
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "Box::new(".to_string()),
|
||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.note(
|
||||
"for more on the distinction between the stack and the heap, read \
|
||||
https://doc.rust-lang.org/book/ch15-01-box.html, \
|
||||
https://doc.rust-lang.org/rust-by-example/std/box.html, and \
|
||||
https://doc.rust-lang.org/std/boxed/index.html",
|
||||
);
|
||||
if self.can_coerce(self.tcx.mk_box(found), expected) {
|
||||
let suggest_boxing = match found.kind() {
|
||||
ty::Tuple(tuple) if tuple.is_empty() => {
|
||||
SuggestBoxing::Unit { start: span.shrink_to_lo(), end: span }
|
||||
}
|
||||
ty::Generator(def_id, ..)
|
||||
if matches!(
|
||||
self.tcx.generator_kind(def_id),
|
||||
Some(GeneratorKind::Async(AsyncGeneratorKind::Closure))
|
||||
) =>
|
||||
{
|
||||
SuggestBoxing::AsyncBody
|
||||
}
|
||||
_ => SuggestBoxing::Other { start: span.shrink_to_lo(), end: span.shrink_to_hi() },
|
||||
};
|
||||
err.subdiagnostic(suggest_boxing);
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
@ -26,7 +26,7 @@ use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, Var
|
||||
|
||||
bitflags! {
|
||||
#[derive(HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct AdtFlags: u32 {
|
||||
pub struct AdtFlags: u16 {
|
||||
const NO_ADT_FLAGS = 0;
|
||||
/// Indicates whether the ADT is an enum.
|
||||
const IS_ENUM = 1 << 0;
|
||||
|
@ -1093,11 +1093,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
v.0
|
||||
}
|
||||
|
||||
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type and associated alias span when type alias is used
|
||||
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
|
||||
/// its return type, and the associated alias span when type alias is used,
|
||||
/// along with a span for lifetime suggestion (if there are existing generics).
|
||||
pub fn return_type_impl_or_dyn_traits_with_type_alias(
|
||||
self,
|
||||
scope_def_id: LocalDefId,
|
||||
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
|
||||
) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
|
||||
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
||||
let mut v = TraitObjectVisitor(vec![], self.hir());
|
||||
// when the return type is a type alias
|
||||
@ -1111,7 +1113,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
{
|
||||
v.visit_ty(alias_ty);
|
||||
if !v.0.is_empty() {
|
||||
return Some((v.0, alias_generics.span));
|
||||
return Some((v.0, alias_generics.span, alias_generics.span_for_lifetime_suggestion()));
|
||||
}
|
||||
}
|
||||
return None;
|
||||
|
@ -115,7 +115,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
|
||||
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
|
||||
let ty = tcx.type_of(self.def.def_id());
|
||||
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty.skip_binder())
|
||||
tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
|
||||
}
|
||||
|
||||
/// Finds a crate that contains a monomorphization of this instance that
|
||||
@ -578,14 +578,15 @@ impl<'tcx> Instance<'tcx> {
|
||||
self.def.has_polymorphic_mir_body().then_some(self.substs)
|
||||
}
|
||||
|
||||
pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T
|
||||
pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
|
||||
{
|
||||
let v = v.map_bound(|v| *v);
|
||||
if let Some(substs) = self.substs_for_mir_body() {
|
||||
EarlyBinder(*v).subst(tcx, substs)
|
||||
v.subst(tcx, substs)
|
||||
} else {
|
||||
*v
|
||||
v.skip_binder()
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,7 +595,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
v: T,
|
||||
v: EarlyBinder<T>,
|
||||
) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
|
||||
@ -602,7 +603,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
if let Some(substs) = self.substs_for_mir_body() {
|
||||
tcx.subst_and_normalize_erasing_regions(substs, param_env, v)
|
||||
} else {
|
||||
tcx.normalize_erasing_regions(param_env, v)
|
||||
tcx.normalize_erasing_regions(param_env, v.skip_binder())
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +612,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
v: T,
|
||||
v: EarlyBinder<T>,
|
||||
) -> Result<T, NormalizationError<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
|
||||
@ -619,7 +620,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
if let Some(substs) = self.substs_for_mir_body() {
|
||||
tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
|
||||
} else {
|
||||
tcx.try_normalize_erasing_regions(param_env, v)
|
||||
tcx.try_normalize_erasing_regions(param_env, v.skip_binder())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1739,7 +1739,7 @@ pub struct Destructor {
|
||||
|
||||
bitflags! {
|
||||
#[derive(HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct VariantFlags: u32 {
|
||||
pub struct VariantFlags: u8 {
|
||||
const NO_VARIANT_FLAGS = 0;
|
||||
/// Indicates whether the field list of this variant is `#[non_exhaustive]`.
|
||||
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
|
||||
|
@ -139,7 +139,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self,
|
||||
param_substs: SubstsRef<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: T,
|
||||
value: EarlyBinder<T>,
|
||||
) -> T
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
@ -151,7 +151,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
param_env={:?})",
|
||||
param_substs, value, param_env,
|
||||
);
|
||||
let substituted = EarlyBinder(value).subst(self, param_substs);
|
||||
let substituted = value.subst(self, param_substs);
|
||||
self.normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self,
|
||||
param_substs: SubstsRef<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: T,
|
||||
value: EarlyBinder<T>,
|
||||
) -> Result<T, NormalizationError<'tcx>>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
@ -175,7 +175,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
param_env={:?})",
|
||||
param_substs, value, param_env,
|
||||
);
|
||||
let substituted = EarlyBinder(value).subst(self, param_substs);
|
||||
let substituted = value.subst(self, param_substs);
|
||||
self.try_normalize_erasing_regions(param_env, substituted)
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ impl<'tcx> Inliner<'tcx> {
|
||||
let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
self.param_env,
|
||||
callee_body.clone(),
|
||||
ty::EarlyBinder(callee_body.clone()),
|
||||
) else {
|
||||
return Err("failed to normalize callee body");
|
||||
};
|
||||
@ -444,7 +444,9 @@ impl<'tcx> Inliner<'tcx> {
|
||||
work_list.push(target);
|
||||
|
||||
// If the place doesn't actually need dropping, treat it like a regular goto.
|
||||
let ty = callsite.callee.subst_mir(self.tcx, &place.ty(callee_body, tcx).ty);
|
||||
let ty = callsite
|
||||
.callee
|
||||
.subst_mir(self.tcx, ty::EarlyBinder(&place.ty(callee_body, tcx).ty));
|
||||
if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
|
||||
work_list.push(unwind);
|
||||
}
|
||||
@ -788,7 +790,9 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
||||
match terminator.kind {
|
||||
TerminatorKind::Drop { ref place, unwind, .. } => {
|
||||
// If the place doesn't actually need dropping, treat it like a regular goto.
|
||||
let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty);
|
||||
let ty = self
|
||||
.instance
|
||||
.subst_mir(tcx, ty::EarlyBinder(&place.ty(self.callee_body, tcx).ty));
|
||||
if ty.needs_drop(tcx, self.param_env) {
|
||||
self.cost += CALL_PENALTY;
|
||||
if let UnwindAction::Cleanup(_) = unwind {
|
||||
@ -799,7 +803,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
|
||||
let fn_ty = self.instance.subst_mir(tcx, &f.literal.ty());
|
||||
let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder(&f.literal.ty()));
|
||||
self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
|
||||
// Don't give intrinsics the extra penalty for calls
|
||||
INSTR_COST
|
||||
|
@ -44,7 +44,11 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
|
||||
) -> bool {
|
||||
trace!(%caller);
|
||||
for &(callee, substs) in tcx.mir_inliner_callees(caller.def) {
|
||||
let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions(tcx, param_env, substs) else {
|
||||
let Ok(substs) = caller.try_subst_mir_and_normalize_erasing_regions(
|
||||
tcx,
|
||||
param_env,
|
||||
ty::EarlyBinder(substs),
|
||||
) else {
|
||||
trace!(?caller, ?param_env, ?substs, "cannot normalize, skipping");
|
||||
continue;
|
||||
};
|
||||
|
@ -677,7 +677,7 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
|
||||
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||
self.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
value,
|
||||
ty::EarlyBinder(value),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
|
||||
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
|
||||
instance.substs,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
tcx.type_of(impl_def_id).skip_binder(),
|
||||
tcx.type_of(impl_def_id),
|
||||
);
|
||||
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
|
||||
return Some(def_id);
|
||||
|
@ -29,12 +29,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
|
||||
let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
|
||||
closure_instance.substs,
|
||||
param_env,
|
||||
before_feature_tys,
|
||||
ty::EarlyBinder(before_feature_tys),
|
||||
);
|
||||
let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
|
||||
closure_instance.substs,
|
||||
param_env,
|
||||
after_feature_tys,
|
||||
ty::EarlyBinder(after_feature_tys),
|
||||
);
|
||||
|
||||
let new_size = tcx
|
||||
|
@ -65,7 +65,7 @@ mod attr_impl {
|
||||
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
|
||||
bitflags::bitflags! {
|
||||
#[derive(Default, HashStable_Generic)]
|
||||
pub struct ArgAttribute: u16 {
|
||||
pub struct ArgAttribute: u8 {
|
||||
const NoAlias = 1 << 1;
|
||||
const NoCapture = 1 << 2;
|
||||
const NonNull = 1 << 3;
|
||||
|
@ -334,7 +334,7 @@ fn associated_type_for_impl_trait_in_trait(
|
||||
parent_count,
|
||||
params,
|
||||
param_def_id_to_index,
|
||||
has_self: false,
|
||||
has_self: opaque_ty_generics.has_self,
|
||||
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
|
||||
}
|
||||
});
|
||||
|
@ -27,8 +27,7 @@ fn resolve_instance<'tcx>(
|
||||
)
|
||||
} else {
|
||||
let ty = tcx.type_of(def);
|
||||
let item_type =
|
||||
tcx.subst_and_normalize_erasing_regions(substs, param_env, ty.skip_binder());
|
||||
let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty);
|
||||
|
||||
let def = match *item_type.kind() {
|
||||
ty::FnDef(def_id, ..) if tcx.is_intrinsic(def_id) => {
|
||||
|
@ -19,7 +19,7 @@ include!("../dylib_util.rs");
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Child, Command};
|
||||
use std::process::{exit, Child, Command};
|
||||
use std::str::FromStr;
|
||||
use std::time::Instant;
|
||||
|
||||
@ -47,7 +47,12 @@ fn main() {
|
||||
} else {
|
||||
("RUSTC_REAL", "RUSTC_LIBDIR")
|
||||
};
|
||||
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
|
||||
let stage = env::var("RUSTC_STAGE").unwrap_or_else(|_| {
|
||||
// Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
|
||||
eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
|
||||
eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
|
||||
exit(101);
|
||||
});
|
||||
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
|
||||
let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);
|
||||
|
||||
|
@ -5,13 +5,18 @@
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::process::{exit, Command};
|
||||
|
||||
include!("../dylib_util.rs");
|
||||
|
||||
fn main() {
|
||||
let args = env::args_os().skip(1).collect::<Vec<_>>();
|
||||
let stage = env::var("RUSTC_STAGE").expect("RUSTC_STAGE was not set");
|
||||
let stage = env::var("RUSTC_STAGE").unwrap_or_else(|_| {
|
||||
// Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
|
||||
eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
|
||||
eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
|
||||
exit(101);
|
||||
});
|
||||
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
|
||||
let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
|
||||
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
|
||||
|
@ -385,6 +385,9 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
||||
Node::Expr(parent_expr) => {
|
||||
if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
|
||||
{
|
||||
// FIXME: the `subst_identity()` below seems incorrect, since we eventually
|
||||
// call `tcx.try_subst_and_normalize_erasing_regions` further down
|
||||
// (i.e., we are explicitly not in the identity context).
|
||||
let fn_sig = cx.tcx.fn_sig(callee_def_id).subst_identity().skip_binder();
|
||||
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
|
||||
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
|
||||
@ -435,7 +438,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
|
||||
let output_ty = fn_sig.output();
|
||||
if output_ty.contains(*param_ty) {
|
||||
if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions(
|
||||
new_subst, cx.param_env, output_ty) {
|
||||
new_subst, cx.param_env, EarlyBinder(output_ty)) {
|
||||
expr = parent_expr;
|
||||
ty = new_ty;
|
||||
continue;
|
||||
|
11
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.rs
Normal file
11
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.rs
Normal file
@ -0,0 +1,11 @@
|
||||
type Lazy<T> = Box<dyn Fn() -> T + 'static>;
|
||||
|
||||
fn test(x: &i32) -> Lazy<i32> {
|
||||
Box::new(|| {
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
//~| ERROR closure may outlive the current function
|
||||
*x
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {}
|
43
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.stderr
Normal file
43
tests/ui/borrowck/suggest-lt-on-ty-alias-w-generics.stderr
Normal file
@ -0,0 +1,43 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:5
|
||||
|
|
||||
LL | fn test(x: &i32) -> Lazy<i32> {
|
||||
| - let's call the lifetime of this reference `'1`
|
||||
LL | / Box::new(|| {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | *x
|
||||
LL | | })
|
||||
| |______^ returning this value requires that `'1` must outlive `'static`
|
||||
|
|
||||
help: to declare that the trait object captures data from argument `x`, you can add a lifetime parameter `'a` in the type alias
|
||||
|
|
||||
LL | type Lazy<'a, T> = Box<dyn Fn() -> T + 'a>;
|
||||
| +++ ~~
|
||||
|
||||
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
|
||||
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:14
|
||||
|
|
||||
LL | Box::new(|| {
|
||||
| ^^ may outlive borrowed value `x`
|
||||
...
|
||||
LL | *x
|
||||
| -- `x` is borrowed here
|
||||
|
|
||||
note: closure is returned here
|
||||
--> $DIR/suggest-lt-on-ty-alias-w-generics.rs:4:5
|
||||
|
|
||||
LL | / Box::new(|| {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | *x
|
||||
LL | | })
|
||||
| |______^
|
||||
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
||||
|
|
||||
LL | Box::new(move || {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0373`.
|
12
tests/ui/issues/auxiliary/issue-111011.rs
Normal file
12
tests/ui/issues/auxiliary/issue-111011.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![feature(async_closure)]
|
||||
|
||||
// edition:2021
|
||||
|
||||
fn foo<X>(x: impl FnOnce() -> Box<X>) {}
|
||||
// just to make sure async closures can still be suggested for boxing.
|
||||
fn bar<X>(x: Box<dyn FnOnce() -> X>) {}
|
||||
|
||||
fn main() {
|
||||
foo(async move || {}); //~ ERROR mismatched types
|
||||
bar(async move || {}); //~ ERROR mismatched types
|
||||
}
|
34
tests/ui/issues/auxiliary/issue-111011.stderr
Normal file
34
tests/ui/issues/auxiliary/issue-111011.stderr
Normal file
@ -0,0 +1,34 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-111011.rs:10:23
|
||||
|
|
||||
LL | foo(async move || {});
|
||||
| ^^ expected `Box<_>`, found `async` closure body
|
||||
|
|
||||
= note: expected struct `Box<_>`
|
||||
found `async` closure body `[async closure body@$DIR/issue-111011.rs:10:23: 10:25]`
|
||||
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-111011.rs:11:9
|
||||
|
|
||||
LL | bar(async move || {});
|
||||
| --- ^^^^^^^^^^^^^^^^ expected `Box<dyn FnOnce() -> _>`, found closure
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected struct `Box<(dyn FnOnce() -> _ + 'static)>`
|
||||
found closure `[closure@$DIR/issue-111011.rs:11:9: 11:22]`
|
||||
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||
note: function defined here
|
||||
--> $DIR/issue-111011.rs:7:4
|
||||
|
|
||||
LL | fn bar<X>(x: Box<dyn FnOnce() -> X>) {}
|
||||
| ^^^ -------------------------
|
||||
help: store this in the heap by calling `Box::new`
|
||||
|
|
||||
LL | bar(Box::new(async move || {}));
|
||||
| +++++++++ +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -1,6 +1,5 @@
|
||||
// build-fail
|
||||
// compile-flags:-C link-arg=märchenhaft
|
||||
// compile-flags:-C link-arg=⦺ⅈ⽯⭏⽽◃⡽⚞
|
||||
// only-msvc
|
||||
// error-pattern:= note: LINK : fatal error LNK1181:
|
||||
// normalize-stderr-test "(\s*\|\n)\s*= note: .*\n" -> "$1"
|
||||
// normalize-stderr-test "(?:.|\n)*(⦺ⅈ⽯⭏⽽◃⡽⚞)(?:.|\n)*" -> "$1"
|
||||
pub fn main() {}
|
||||
|
@ -1,7 +1 @@
|
||||
error: linking with `link.exe` failed: exit code: 1181
|
||||
|
|
||||
= note: LINK : fatal error LNK1181: cannot open input file 'märchenhaft.obj'
|
||||
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
⦺ⅈ⽯⭏⽽◃⡽⚞
|
12
tests/ui/suggestions/suggest-boxed-empty-block.fixed
Normal file
12
tests/ui/suggestions/suggest-boxed-empty-block.fixed
Normal file
@ -0,0 +1,12 @@
|
||||
#![feature(async_closure)]
|
||||
|
||||
// edition:2021
|
||||
// run-rustfix
|
||||
|
||||
fn foo<T>(_: Box<T>) {}
|
||||
fn bar<T>(_: impl Fn() -> Box<T>) {}
|
||||
|
||||
fn main() {
|
||||
foo(Box::new(())); //~ ERROR mismatched types
|
||||
bar(|| Box::new(())); //~ ERROR mismatched types
|
||||
}
|
12
tests/ui/suggestions/suggest-boxed-empty-block.rs
Normal file
12
tests/ui/suggestions/suggest-boxed-empty-block.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![feature(async_closure)]
|
||||
|
||||
// edition:2021
|
||||
// run-rustfix
|
||||
|
||||
fn foo<T>(_: Box<T>) {}
|
||||
fn bar<T>(_: impl Fn() -> Box<T>) {}
|
||||
|
||||
fn main() {
|
||||
foo({}); //~ ERROR mismatched types
|
||||
bar(|| {}); //~ ERROR mismatched types
|
||||
}
|
33
tests/ui/suggestions/suggest-boxed-empty-block.stderr
Normal file
33
tests/ui/suggestions/suggest-boxed-empty-block.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-boxed-empty-block.rs:10:9
|
||||
|
|
||||
LL | foo({});
|
||||
| ^^ expected `Box<_>`, found `()`
|
||||
|
|
||||
= note: expected struct `Box<_>`
|
||||
found unit type `()`
|
||||
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||
help: store this in the heap by calling `Box::new`
|
||||
|
|
||||
LL - foo({});
|
||||
LL + foo(Box::new(()));
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-boxed-empty-block.rs:11:12
|
||||
|
|
||||
LL | bar(|| {});
|
||||
| ^^ expected `Box<_>`, found `()`
|
||||
|
|
||||
= note: expected struct `Box<_>`
|
||||
found unit type `()`
|
||||
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
|
||||
help: store this in the heap by calling `Box::new`
|
||||
|
|
||||
LL - bar(|| {});
|
||||
LL + bar(|| Box::new(()));
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user