Skip to content

Commit e6e620e

Browse files
committed
Auto merge of rust-lang#89527 - ehuss:beta-backports, r=ehuss
[beta] Beta rollup * Fix WinUWP std compilation errors due to I/O safety rust-lang#88587 * Disable RemoveZsts in generators to avoid query cycles rust-lang#88979 * Disable the evaluation cache when in intercrate mode rust-lang#88994 * Fix linting when trailing macro expands to a trailing semi rust-lang#88996 * Don't use projection cache or candidate cache in intercrate mode rust-lang#89125 * 2229: Mark insignificant dtor in stdlib rust-lang#89144 * Temporarily rename int_roundings functions to avoid conflicts rust-lang#89184 * [rfc 2229] Drop fully captured upvars in the same order as the regular drop code rust-lang#89208 * Use the correct edition for syntax highlighting doctests rust-lang#89277 * Don't normalize opaque types with escaping late-bound regions rust-lang#89285 * Update Let's Encrypt ROOT CA certificate in dist-(i686|x86_64)-linux docker images rust-lang#89486 Cargo update: * - [beta] 1.56 backports (rust-lang/cargo#9958) * - [beta] Revert "When a dependency does not have a version, git or path… (rust-lang/cargo#9912) * - [beta] Fix rustc --profile=dev unstable check. (rust-lang/cargo#9901)
2 parents deef866 + 06b37f1 commit e6e620e

File tree

62 files changed

+1087
-640
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1087
-640
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -871,9 +871,9 @@ dependencies = [
871871

872872
[[package]]
873873
name = "curl-sys"
874-
version = "0.4.45+curl-7.78.0"
874+
version = "0.4.49+curl-7.79.1"
875875
source = "registry+https://github.com/rust-lang/crates.io-index"
876-
checksum = "de9e5a72b1c744eb5dd20b2be4d7eb84625070bb5c4ab9b347b70464ab1e62eb"
876+
checksum = "e0f44960aea24a786a46907b8824ebc0e66ca06bf4e4978408c7499620343483"
877877
dependencies = [
878878
"cc",
879879
"libc",

compiler/rustc_expand/src/expand.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -1373,14 +1373,17 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13731373
// `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
13741374
// See #78991 for an investigation of treating macros in this position
13751375
// as statements, rather than expressions, during parsing.
1376-
if let StmtKind::Expr(expr) = &stmt.kind {
1377-
if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) {
1376+
let res = match &stmt.kind {
1377+
StmtKind::Expr(expr)
1378+
if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) =>
1379+
{
13781380
self.cx.current_expansion.is_trailing_mac = true;
1381+
// Don't use `assign_id` for this statement - it may get removed
1382+
// entirely due to a `#[cfg]` on the contained expression
1383+
noop_flat_map_stmt(stmt, self)
13791384
}
1380-
}
1381-
1382-
let res = assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self));
1383-
1385+
_ => assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)),
1386+
};
13841387
self.cx.current_expansion.is_trailing_mac = false;
13851388
res
13861389
}

compiler/rustc_mir/src/transform/remove_zsts.rs

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ pub struct RemoveZsts;
99

1010
impl<'tcx> MirPass<'tcx> for RemoveZsts {
1111
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
12+
// Avoid query cycles (generators require optimized MIR for layout).
13+
if tcx.type_of(body.source.def_id()).is_generator() {
14+
return;
15+
}
1216
let param_env = tcx.param_env(body.source.def_id());
1317
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
1418
for block in basic_blocks.iter_mut() {

compiler/rustc_trait_selection/src/traits/project.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -388,15 +388,15 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
388388
// to make sure we don't forget to fold the substs regardless.
389389

390390
match *ty.kind() {
391-
ty::Opaque(def_id, substs) => {
391+
// This is really important. While we *can* handle this, this has
392+
// severe performance implications for large opaque types with
393+
// late-bound regions. See `issue-88862` benchmark.
394+
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
392395
// Only normalize `impl Trait` after type-checking, usually in codegen.
393396
match self.param_env.reveal() {
394397
Reveal::UserFacing => ty.super_fold_with(self),
395398

396399
Reveal::All => {
397-
// N.b. there is an assumption here all this code can handle
398-
// escaping bound vars.
399-
400400
let recursion_limit = self.tcx().recursion_limit();
401401
if !recursion_limit.value_within_limit(self.depth) {
402402
let obligation = Obligation::with_depth(
@@ -844,6 +844,10 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
844844
obligations: &mut Vec<PredicateObligation<'tcx>>,
845845
) -> Result<Option<Ty<'tcx>>, InProgress> {
846846
let infcx = selcx.infcx();
847+
// Don't use the projection cache in intercrate mode -
848+
// the `infcx` may be re-used between intercrate in non-intercrate
849+
// mode, which could lead to using incorrect cache results.
850+
let use_cache = !selcx.is_intercrate();
847851

848852
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
849853
let cache_key = ProjectionCacheKey::new(projection_ty);
@@ -856,7 +860,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
856860
// bounds. It might be the case that we want two distinct caches,
857861
// or else another kind of cache entry.
858862

859-
let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
863+
let cache_result = if use_cache {
864+
infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
865+
} else {
866+
Ok(())
867+
};
860868
match cache_result {
861869
Ok(()) => debug!("no cache"),
862870
Err(ProjectionCacheEntry::Ambiguous) => {
@@ -881,7 +889,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
881889
// should ensure that, unless this happens within a snapshot that's
882890
// rolled back, fulfillment or evaluation will notice the cycle.
883891

884-
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
892+
if use_cache {
893+
infcx.inner.borrow_mut().projection_cache().recur(cache_key);
894+
}
885895
return Err(InProgress);
886896
}
887897
Err(ProjectionCacheEntry::Recur) => {
@@ -963,20 +973,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
963973
.map_or(false, |res| res.must_apply_considering_regions())
964974
});
965975

966-
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
976+
if use_cache {
977+
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
978+
}
967979
obligations.extend(result.obligations);
968980
Ok(Some(result.value))
969981
}
970982
Ok(ProjectedTy::NoProgress(projected_ty)) => {
971983
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
972984
let result = Normalized { value: projected_ty, obligations: vec![] };
973-
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
985+
if use_cache {
986+
infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
987+
}
974988
// No need to extend `obligations`.
975989
Ok(Some(result.value))
976990
}
977991
Err(ProjectionTyError::TooManyCandidates) => {
978992
debug!("opt_normalize_projection_type: too many candidates");
979-
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
993+
if use_cache {
994+
infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
995+
}
980996
Ok(None)
981997
}
982998
Err(ProjectionTyError::TraitSelectionError(_)) => {
@@ -986,7 +1002,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
9861002
// Trait`, which when processed will cause the error to be
9871003
// reported later
9881004

989-
infcx.inner.borrow_mut().projection_cache().error(cache_key);
1005+
if use_cache {
1006+
infcx.inner.borrow_mut().projection_cache().error(cache_key);
1007+
}
9901008
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
9911009
obligations.extend(result.obligations);
9921010
Ok(Some(result.value))

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,15 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
206206

207207
// Wrap this in a closure so we don't accidentally return from the outer function
208208
let res = (|| match *ty.kind() {
209-
ty::Opaque(def_id, substs) => {
209+
// This is really important. While we *can* handle this, this has
210+
// severe performance implications for large opaque types with
211+
// late-bound regions. See `issue-88862` benchmark.
212+
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
210213
// Only normalize `impl Trait` after type-checking, usually in codegen.
211214
match self.param_env.reveal() {
212215
Reveal::UserFacing => ty.super_fold_with(self),
213216

214217
Reveal::All => {
215-
// N.b. there is an assumption here all this code can handle
216-
// escaping bound vars.
217-
218218
let substs = substs.super_fold_with(self);
219219
let recursion_limit = self.tcx().recursion_limit();
220220
if !recursion_limit.value_within_limit(self.anon_depth) {

compiler/rustc_trait_selection/src/traits/select/mod.rs

+34
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
315315
self.infcx.tcx
316316
}
317317

318+
pub fn is_intercrate(&self) -> bool {
319+
self.intercrate
320+
}
321+
318322
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
319323
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
320324
match pred.constness {
@@ -982,6 +986,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
982986
param_env: ty::ParamEnv<'tcx>,
983987
trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
984988
) -> Option<EvaluationResult> {
989+
// Neither the global nor local cache is aware of intercrate
990+
// mode, so don't do any caching. In particular, we might
991+
// re-use the same `InferCtxt` with both an intercrate
992+
// and non-intercrate `SelectionContext`
993+
if self.intercrate {
994+
return None;
995+
}
996+
985997
let tcx = self.tcx();
986998
if self.can_use_global_caches(param_env) {
987999
if let Some(res) = tcx.evaluation_cache.get(&param_env.and(trait_ref), tcx) {
@@ -1004,6 +1016,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10041016
return;
10051017
}
10061018

1019+
// Neither the global nor local cache is aware of intercrate
1020+
// mode, so don't do any caching. In particular, we might
1021+
// re-use the same `InferCtxt` with both an intercrate
1022+
// and non-intercrate `SelectionContext`
1023+
if self.intercrate {
1024+
return;
1025+
}
1026+
10071027
if self.can_use_global_caches(param_env) {
10081028
if !trait_ref.needs_infer() {
10091029
debug!(?trait_ref, ?result, "insert_evaluation_cache global");
@@ -1185,6 +1205,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11851205
param_env: ty::ParamEnv<'tcx>,
11861206
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
11871207
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
1208+
// Neither the global nor local cache is aware of intercrate
1209+
// mode, so don't do any caching. In particular, we might
1210+
// re-use the same `InferCtxt` with both an intercrate
1211+
// and non-intercrate `SelectionContext`
1212+
if self.intercrate {
1213+
return None;
1214+
}
11881215
let tcx = self.tcx();
11891216
let pred = &cache_fresh_trait_pred.skip_binder();
11901217
let trait_ref = pred.trait_ref;
@@ -1221,6 +1248,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12211248
&self,
12221249
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
12231250
) -> bool {
1251+
// Neither the global nor local cache is aware of intercrate
1252+
// mode, so don't do any caching. In particular, we might
1253+
// re-use the same `InferCtxt` with both an intercrate
1254+
// and non-intercrate `SelectionContext`
1255+
if self.intercrate {
1256+
return false;
1257+
}
12241258
match result {
12251259
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
12261260
_ => true,

compiler/rustc_ty_utils/src/needs_drop.rs

+58-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_hir::def_id::DefId;
55
use rustc_middle::ty::subst::Subst;
6+
use rustc_middle::ty::subst::SubstsRef;
67
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
78
use rustc_middle::ty::{self, Ty, TyCtxt};
89
use rustc_session::Limit;
@@ -12,7 +13,8 @@ type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
1213

1314
fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
1415
let adt_fields =
15-
move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
16+
move |adt_def: &ty::AdtDef, _| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
17+
1618
// If we don't know a type doesn't need drop, for example if it's a type
1719
// parameter without a `Copy` bound, then we conservatively return that it
1820
// needs drop.
@@ -25,8 +27,9 @@ fn has_significant_drop_raw<'tcx>(
2527
tcx: TyCtxt<'tcx>,
2628
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
2729
) -> bool {
28-
let significant_drop_fields =
29-
move |adt_def: &ty::AdtDef| tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter());
30+
let significant_drop_fields = move |adt_def: &ty::AdtDef, _| {
31+
tcx.adt_significant_drop_tys(adt_def.did).map(|tys| tys.iter())
32+
};
3033
let res = NeedsDropTypes::new(tcx, query.param_env, query.value, significant_drop_fields)
3134
.next()
3235
.is_some();
@@ -71,7 +74,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> {
7174

7275
impl<'tcx, F, I> Iterator for NeedsDropTypes<'tcx, F>
7376
where
74-
F: Fn(&ty::AdtDef) -> NeedsDropResult<I>,
77+
F: Fn(&ty::AdtDef, SubstsRef<'tcx>) -> NeedsDropResult<I>,
7578
I: Iterator<Item = Ty<'tcx>>,
7679
{
7780
type Item = NeedsDropResult<Ty<'tcx>>;
@@ -135,7 +138,7 @@ where
135138
// `ManuallyDrop`. If it's a struct or enum without a `Drop`
136139
// impl then check whether the field types need `Drop`.
137140
ty::Adt(adt_def, substs) => {
138-
let tys = match (self.adt_components)(adt_def) {
141+
let tys = match (self.adt_components)(adt_def, substs) {
139142
Err(e) => return Some(Err(e)),
140143
Ok(tys) => tys,
141144
};
@@ -168,22 +171,44 @@ where
168171
}
169172
}
170173

174+
enum DtorType {
175+
/// Type has a `Drop` but it is considered insignificant.
176+
/// Check the query `adt_significant_drop_tys` for understanding
177+
/// "significant" / "insignificant".
178+
Insignificant,
179+
180+
/// Type has a `Drop` implentation.
181+
Significant,
182+
}
183+
171184
// This is a helper function for `adt_drop_tys` and `adt_significant_drop_tys`.
172185
// Depending on the implentation of `adt_has_dtor`, it is used to check if the
173186
// ADT has a destructor or if the ADT only has a significant destructor. For
174187
// understanding significant destructor look at `adt_significant_drop_tys`.
175-
fn adt_drop_tys_helper(
176-
tcx: TyCtxt<'_>,
188+
fn adt_drop_tys_helper<'tcx>(
189+
tcx: TyCtxt<'tcx>,
177190
def_id: DefId,
178-
adt_has_dtor: impl Fn(&ty::AdtDef) -> bool,
179-
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
180-
let adt_components = move |adt_def: &ty::AdtDef| {
191+
adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>,
192+
) -> Result<&ty::List<Ty<'tcx>>, AlwaysRequiresDrop> {
193+
let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| {
181194
if adt_def.is_manually_drop() {
182195
debug!("adt_drop_tys: `{:?}` is manually drop", adt_def);
183196
return Ok(Vec::new().into_iter());
184-
} else if adt_has_dtor(adt_def) {
185-
debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
186-
return Err(AlwaysRequiresDrop);
197+
} else if let Some(dtor_info) = adt_has_dtor(adt_def) {
198+
match dtor_info {
199+
DtorType::Significant => {
200+
debug!("adt_drop_tys: `{:?}` implements `Drop`", adt_def);
201+
return Err(AlwaysRequiresDrop);
202+
}
203+
DtorType::Insignificant => {
204+
debug!("adt_drop_tys: `{:?}` drop is insignificant", adt_def);
205+
206+
// Since the destructor is insignificant, we just want to make sure all of
207+
// the passed in type parameters are also insignificant.
208+
// Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex.
209+
return Ok(substs.types().collect::<Vec<Ty<'_>>>().into_iter());
210+
}
211+
}
187212
} else if adt_def.is_union() {
188213
debug!("adt_drop_tys: `{:?}` is a union", adt_def);
189214
return Ok(Vec::new().into_iter());
@@ -201,7 +226,10 @@ fn adt_drop_tys_helper(
201226
}
202227

203228
fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
204-
let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).is_some();
229+
// This is for the "needs_drop" query, that considers all `Drop` impls, therefore all dtors are
230+
// significant.
231+
let adt_has_dtor =
232+
|adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant);
205233
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
206234
}
207235

@@ -210,10 +238,22 @@ fn adt_significant_drop_tys(
210238
def_id: DefId,
211239
) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> {
212240
let adt_has_dtor = |adt_def: &ty::AdtDef| {
213-
adt_def
214-
.destructor(tcx)
215-
.map(|dtor| !tcx.has_attr(dtor.did, sym::rustc_insignificant_dtor))
216-
.unwrap_or(false)
241+
let is_marked_insig = tcx.has_attr(adt_def.did, sym::rustc_insignificant_dtor);
242+
if is_marked_insig {
243+
// In some cases like `std::collections::HashMap` where the struct is a wrapper around
244+
// a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies
245+
// outside stdlib, we might choose to still annotate the the wrapper (std HashMap) with
246+
// `rustc_insignificant_dtor`, even if the type itself doesn't have a `Drop` impl.
247+
Some(DtorType::Insignificant)
248+
} else if adt_def.destructor(tcx).is_some() {
249+
// There is a Drop impl and the type isn't marked insignificant, therefore Drop must be
250+
// significant.
251+
Some(DtorType::Significant)
252+
} else {
253+
// No destructor found nor the type is annotated with `rustc_insignificant_dtor`, we
254+
// treat this as the simple case of Drop impl for type.
255+
None
256+
}
217257
};
218258
adt_drop_tys_helper(tcx, def_id, adt_has_dtor)
219259
}

0 commit comments

Comments
 (0)