Skip to content

Commit b13a5bf

Browse files
committed
Auto merge of #92927 - matthiaskrgr:rollup-pgzwfcm, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #92747 (Simplification of BigNum::bit_length) - #92767 (Use the new language identifier for Rust in the PDB debug format) - #92775 (Inline std::os::unix::ffi::OsStringExt methods) - #92863 (Remove `&mut` from `io::read_to_string` signature) - #92865 (Ignore static lifetimes for GATs outlives lint) - #92873 (Generate more precise generator names) - #92879 (Add Sync bound to allocator parameter in vec::IntoIter) - #92892 (Do not fail evaluation in const blocks) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 38c22af + 539175c commit b13a5bf

File tree

14 files changed

+157
-70
lines changed

14 files changed

+157
-70
lines changed

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -519,12 +519,18 @@ fn push_unqualified_item_name(
519519
output.push_str(tcx.crate_name(def_id.krate).as_str());
520520
}
521521
DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
522+
let key = match tcx.generator_kind(def_id).unwrap() {
523+
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block",
524+
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure",
525+
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn",
526+
hir::GeneratorKind::Gen => "generator",
527+
};
522528
// Generators look like closures, but we want to treat them differently
523529
// in the debug info.
524530
if cpp_like_debuginfo(tcx) {
525-
write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
531+
write!(output, "{}${}", key, disambiguated_data.disambiguator).unwrap();
526532
} else {
527-
write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
533+
write!(output, "{{{}#{}}}", key, disambiguated_data.disambiguator).unwrap();
528534
}
529535
}
530536
_ => match disambiguated_data.data.name() {

compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1226,7 +1226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12261226
let body = self.tcx.hir().body(anon_const.body);
12271227

12281228
// Create a new function context.
1229-
let fcx = FnCtxt::new(self, self.param_env, body.value.hir_id);
1229+
let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id);
12301230
crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
12311231

12321232
let ty = fcx.check_expr_with_expectation(&body.value, expected);

compiler/rustc_typeck/src/check/wfcheck.rs

+48-46
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use rustc_hir::lang_items::LangItem;
1414
use rustc_hir::ItemKind;
1515
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
1616
use rustc_infer::infer::outlives::obligations::TypeOutlives;
17-
use rustc_infer::infer::TyCtxtInferExt;
18-
use rustc_infer::infer::{self, RegionckMode, SubregionOrigin};
17+
use rustc_infer::infer::region_constraints::GenericKind;
18+
use rustc_infer::infer::{self, RegionckMode};
19+
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
1920
use rustc_middle::hir::map as hir_map;
2021
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
2122
use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -332,6 +333,12 @@ fn check_gat_where_clauses(
332333
// outlives relationship (`Self: 'a`), then we want to ensure that is
333334
// reflected in a where clause on the GAT itself.
334335
for (region, region_idx) in &regions {
336+
// Ignore `'static` lifetimes for the purpose of this lint: it's
337+
// because we know it outlives everything and so doesn't give meaninful
338+
// clues
339+
if let ty::ReStatic = region {
340+
continue;
341+
}
335342
for (ty, ty_idx) in &types {
336343
// In our example, requires that Self: 'a
337344
if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) {
@@ -371,10 +378,19 @@ fn check_gat_where_clauses(
371378
// outlives relationship, then we want to ensure that is
372379
// reflected in a where clause on the GAT itself.
373380
for (region_a, region_a_idx) in &regions {
381+
// Ignore `'static` lifetimes for the purpose of this lint: it's
382+
// because we know it outlives everything and so doesn't give meaninful
383+
// clues
384+
if let ty::ReStatic = region_a {
385+
continue;
386+
}
374387
for (region_b, region_b_idx) in &regions {
375388
if region_a == region_b {
376389
continue;
377390
}
391+
if let ty::ReStatic = region_b {
392+
continue;
393+
}
378394

379395
if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
380396
debug!(?region_a_idx, ?region_b_idx);
@@ -502,8 +518,6 @@ fn check_gat_where_clauses(
502518
}
503519
}
504520

505-
// FIXME(jackh726): refactor some of the shared logic between the two functions below
506-
507521
/// Given a known `param_env` and a set of well formed types, can we prove that
508522
/// `ty` outlives `region`.
509523
fn ty_known_to_outlive<'tcx>(
@@ -514,54 +528,49 @@ fn ty_known_to_outlive<'tcx>(
514528
ty: Ty<'tcx>,
515529
region: ty::Region<'tcx>,
516530
) -> bool {
517-
// Unfortunately, we have to use a new `InferCtxt` each call, because
518-
// region constraints get added and solved there and we need to test each
519-
// call individually.
520-
tcx.infer_ctxt().enter(|infcx| {
521-
let mut outlives_environment = OutlivesEnvironment::new(param_env);
522-
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
523-
outlives_environment.save_implied_bounds(id);
524-
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
525-
526-
let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
527-
528-
let sup_type = ty;
529-
let sub_region = region;
530-
531-
let origin = SubregionOrigin::from_obligation_cause(&cause, || {
532-
infer::RelateParamBound(cause.span, sup_type, None)
533-
});
534-
531+
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
532+
let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
535533
let outlives = &mut TypeOutlives::new(
536-
&infcx,
534+
infcx,
537535
tcx,
538-
&region_bound_pairs,
536+
region_bound_pairs,
539537
Some(infcx.tcx.lifetimes.re_root_empty),
540538
param_env,
541539
);
542-
outlives.type_must_outlive(origin, sup_type, sub_region);
543-
544-
let errors = infcx.resolve_regions(
545-
id.expect_owner().to_def_id(),
546-
&outlives_environment,
547-
RegionckMode::default(),
548-
);
549-
550-
debug!(?errors, "errors");
551-
552-
// If we were able to prove that the type outlives the region without
553-
// an error, it must be because of the implied or explicit bounds...
554-
errors.is_empty()
540+
outlives.type_must_outlive(origin, ty, region);
555541
})
556542
}
557543

544+
/// Given a known `param_env` and a set of well formed types, can we prove that
545+
/// `region_a` outlives `region_b`
558546
fn region_known_to_outlive<'tcx>(
559547
tcx: TyCtxt<'tcx>,
560548
id: hir::HirId,
561549
param_env: ty::ParamEnv<'tcx>,
562550
wf_tys: &FxHashSet<Ty<'tcx>>,
563551
region_a: ty::Region<'tcx>,
564552
region_b: ty::Region<'tcx>,
553+
) -> bool {
554+
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |mut infcx, _| {
555+
use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
556+
let origin = infer::RelateRegionParamBound(DUMMY_SP);
557+
// `region_a: region_b` -> `region_b <= region_a`
558+
infcx.push_sub_region_constraint(origin, region_b, region_a);
559+
})
560+
}
561+
562+
/// Given a known `param_env` and a set of well formed types, set up an
563+
/// `InferCtxt`, call the passed function (to e.g. set up region constraints
564+
/// to be tested), then resolve region and return errors
565+
fn resolve_regions_with_wf_tys<'tcx>(
566+
tcx: TyCtxt<'tcx>,
567+
id: hir::HirId,
568+
param_env: ty::ParamEnv<'tcx>,
569+
wf_tys: &FxHashSet<Ty<'tcx>>,
570+
add_constraints: impl for<'a> FnOnce(
571+
&'a InferCtxt<'a, 'tcx>,
572+
&'a Vec<(&'tcx ty::RegionKind, GenericKind<'tcx>)>,
573+
),
565574
) -> bool {
566575
// Unfortunately, we have to use a new `InferCtxt` each call, because
567576
// region constraints get added and solved there and we need to test each
@@ -570,16 +579,9 @@ fn region_known_to_outlive<'tcx>(
570579
let mut outlives_environment = OutlivesEnvironment::new(param_env);
571580
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
572581
outlives_environment.save_implied_bounds(id);
582+
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
573583

574-
let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
575-
576-
let origin = SubregionOrigin::from_obligation_cause(&cause, || {
577-
infer::RelateRegionParamBound(cause.span)
578-
});
579-
580-
use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
581-
// `region_a: region_b` -> `region_b <= region_a`
582-
(&infcx).push_sub_region_constraint(origin, region_b, region_a);
584+
add_constraints(&infcx, region_bound_pairs);
583585

584586
let errors = infcx.resolve_regions(
585587
id.expect_owner().to_def_id(),

library/alloc/src/vec/into_iter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
125125
#[stable(feature = "rust1", since = "1.0.0")]
126126
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
127127
#[stable(feature = "rust1", since = "1.0.0")]
128-
unsafe impl<T: Sync, A: Allocator> Sync for IntoIter<T, A> {}
128+
unsafe impl<T: Sync, A: Allocator + Sync> Sync for IntoIter<T, A> {}
129129

130130
#[stable(feature = "rust1", since = "1.0.0")]
131131
impl<T, A: Allocator> Iterator for IntoIter<T, A> {

library/core/src/num/bignum.rs

+6-15
Original file line numberDiff line numberDiff line change
@@ -158,24 +158,15 @@ macro_rules! define_bignum {
158158
/// Returns the number of bits necessary to represent this value. Note that zero
159159
/// is considered to need 0 bits.
160160
pub fn bit_length(&self) -> usize {
161-
// Skip over the most significant digits which are zero.
161+
let digitbits = <$ty>::BITS as usize;
162162
let digits = self.digits();
163-
let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
164-
let end = digits.len() - zeros;
165-
let nonzero = &digits[..end];
166-
167-
if nonzero.is_empty() {
163+
// Find the most significant non-zero digit.
164+
let msd = digits.iter().rposition(|&x| x != 0);
165+
match msd {
166+
Some(msd) => msd * digitbits + digits[msd].log2() as usize + 1,
168167
// There are no non-zero digits, i.e., the number is zero.
169-
return 0;
170-
}
171-
// This could be optimized with leading_zeros() and bit shifts, but that's
172-
// probably not worth the hassle.
173-
let digitbits = <$ty>::BITS as usize;
174-
let mut i = nonzero.len() * digitbits - 1;
175-
while self.get_bit(i) == 0 {
176-
i -= 1;
168+
_ => 0,
177169
}
178-
i + 1
179170
}
180171

181172
/// Adds `other` to itself and returns its own mutable reference.

library/core/tests/num/bignum.rs

+35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::num::bignum::tests::Big8x3 as Big;
2+
use core::num::bignum::Big32x40;
23

34
#[test]
45
#[should_panic]
@@ -215,6 +216,16 @@ fn test_get_bit_out_of_range() {
215216

216217
#[test]
217218
fn test_bit_length() {
219+
for i in 0..8 * 3 {
220+
// 010000...000
221+
assert_eq!(Big::from_small(1).mul_pow2(i).bit_length(), i + 1);
222+
}
223+
for i in 1..8 * 3 - 1 {
224+
// 010000...001
225+
assert_eq!(Big::from_small(1).mul_pow2(i).add(&Big::from_small(1)).bit_length(), i + 1);
226+
// 110000...000
227+
assert_eq!(Big::from_small(3).mul_pow2(i).bit_length(), i + 2);
228+
}
218229
assert_eq!(Big::from_small(0).bit_length(), 0);
219230
assert_eq!(Big::from_small(1).bit_length(), 1);
220231
assert_eq!(Big::from_small(5).bit_length(), 3);
@@ -223,6 +234,30 @@ fn test_bit_length() {
223234
assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
224235
}
225236

237+
#[test]
238+
fn test_bit_length_32x40() {
239+
for i in 0..32 * 40 {
240+
// 010000...000
241+
assert_eq!(Big32x40::from_small(1).mul_pow2(i).bit_length(), i + 1);
242+
}
243+
for i in 1..32 * 40 - 1 {
244+
// 010000...001
245+
assert_eq!(
246+
Big32x40::from_small(1).mul_pow2(i).add(&Big32x40::from_small(1)).bit_length(),
247+
i + 1
248+
);
249+
// 110000...000
250+
assert_eq!(Big32x40::from_small(3).mul_pow2(i).bit_length(), i + 2);
251+
}
252+
assert_eq!(Big32x40::from_small(0).bit_length(), 0);
253+
assert_eq!(Big32x40::from_small(1).bit_length(), 1);
254+
assert_eq!(Big32x40::from_small(5).bit_length(), 3);
255+
assert_eq!(Big32x40::from_small(0x18).bit_length(), 5);
256+
assert_eq!(Big32x40::from_u64(0x4073).bit_length(), 15);
257+
assert_eq!(Big32x40::from_u64(0xffffff).bit_length(), 24);
258+
assert_eq!(Big32x40::from_u64(0xffffffffffffffff).bit_length(), 64);
259+
}
260+
226261
#[test]
227262
fn test_ord() {
228263
assert!(Big::from_u64(0) < Big::from_u64(0xffffff));

library/std/src/io/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1031,14 +1031,14 @@ pub trait Read {
10311031
///
10321032
/// # use std::io;
10331033
/// fn main() -> io::Result<()> {
1034-
/// let stdin = io::read_to_string(&mut io::stdin())?;
1034+
/// let stdin = io::read_to_string(io::stdin())?;
10351035
/// println!("Stdin was:");
10361036
/// println!("{}", stdin);
10371037
/// Ok(())
10381038
/// }
10391039
/// ```
10401040
#[unstable(feature = "io_read_to_string", issue = "80218")]
1041-
pub fn read_to_string<R: Read>(reader: &mut R) -> Result<String> {
1041+
pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
10421042
let mut buf = String::new();
10431043
reader.read_to_string(&mut buf)?;
10441044
Ok(buf)

library/std/src/os/unix/ffi/os_str.rs

+2
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ pub trait OsStringExt: Sealed {
2828

2929
#[stable(feature = "rust1", since = "1.0.0")]
3030
impl OsStringExt for OsString {
31+
#[inline]
3132
fn from_vec(vec: Vec<u8>) -> OsString {
3233
FromInner::from_inner(Buf { inner: vec })
3334
}
35+
#[inline]
3436
fn into_vec(self) -> Vec<u8> {
3537
self.into_inner().inner
3638
}

src/test/codegen/async-fn-debug-msvc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async fn async_fn_test() {
1717
// FIXME: No way to reliably check the filename.
1818

1919
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
20-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "async_fn$0"
2121
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
2222
// For brevity, we only check the struct name and members of the last variant.
2323
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,

src/test/codegen/async-fn-debug.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async fn async_fn_test() {
1717
// FIXME: No way to reliably check the filename.
1818

1919
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
20-
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]]
20+
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn#0}", scope: [[ASYNC_FN]]
2121
// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
2222
// CHECK-NOT: flags: DIFlagArtificial
2323
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![allow(unused)]
2+
#![feature(const_fn_trait_bound, const_trait_impl, inline_const)]
3+
4+
const fn f<T: ~const Drop>(x: T) {}
5+
6+
struct UnconstDrop;
7+
8+
impl Drop for UnconstDrop {
9+
fn drop(&mut self) {}
10+
}
11+
12+
fn main() {
13+
const {
14+
f(UnconstDrop);
15+
//~^ ERROR the trait bound `UnconstDrop: Drop` is not satisfied
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0277]: the trait bound `UnconstDrop: Drop` is not satisfied
2+
--> $DIR/const-block-const-bound.rs:14:11
3+
|
4+
LL | f(UnconstDrop);
5+
| - ^^^^^^^^^^^ the trait `Drop` is not implemented for `UnconstDrop`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: required by a bound in `f`
10+
--> $DIR/const-block-const-bound.rs:4:15
11+
|
12+
LL | const fn f<T: ~const Drop>(x: T) {}
13+
| ^^^^^^^^^^^ required by this bound in `f`
14+
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
15+
|
16+
LL | fn main() where UnconstDrop: Drop {
17+
| +++++++++++++++++++++++
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/generic-associated-types/self-outlives-lint.rs

+13
Original file line numberDiff line numberDiff line change
@@ -189,4 +189,17 @@ trait Trait: 'static {
189189
fn make_assoc(_: &u32) -> Self::Assoc<'_>;
190190
}
191191

192+
// We ignore `'static` lifetimes for any lints
193+
trait StaticReturn<'a> {
194+
type Y<'b>;
195+
fn foo(&self) -> Self::Y<'static>;
196+
}
197+
198+
// Same as above, but with extra method that takes GAT - just make sure this works
199+
trait StaticReturnAndTakes<'a> {
200+
type Y<'b>;
201+
fn foo(&self) -> Self::Y<'static>;
202+
fn bar<'b>(&self, arg: Self::Y<'b>);
203+
}
204+
192205
fn main() {}

0 commit comments

Comments
 (0)