Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #92927

Merged
merged 18 commits into from
Jan 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
424f38f
Simplification of BigNum::bit_length
swenson Jan 10, 2022
0589cac
Simplify BigNum::bit_length() with log2()
swenson Jan 10, 2022
b03fc76
Use the new language identifier for Rust in the PDB debug format
arlosi Jan 11, 2022
7e6d97b
Inline std::os::unix::ffi::OsStringExt methods
KamilaBorowska Jan 11, 2022
aa0ce4a
Remove `&mut` from `io::read_to_string` signature
camelid Jan 13, 2022
e8e32e4
Ignore static lifetimes for GATs outlives lint
jackh726 Jan 13, 2022
05e1f0d
Generate more precise generator names
eholk Jan 13, 2022
a1173cf
Fix non-MSVC test
eholk Jan 13, 2022
7debb5c
Add Sync bound to allocator parameter in vec::IntoIter
compiler-errors Jan 14, 2022
b9a3c32
Do not fail evaluation in const blocks
compiler-errors Jan 14, 2022
f511360
Rollup merge of #92747 - swenson:bignum-bit-length-optimization, r=sc…
matthiaskrgr Jan 15, 2022
ff1db43
Rollup merge of #92767 - arlosi:pdbenum, r=cuviper
matthiaskrgr Jan 15, 2022
1b241bb
Rollup merge of #92775 - xfix:osstringext-inline, r=m-ou-se
matthiaskrgr Jan 15, 2022
d878ad0
Rollup merge of #92863 - camelid:read_to_string-rm-mut, r=m-ou-se
matthiaskrgr Jan 15, 2022
cd93be0
Rollup merge of #92865 - jackh726:gats-outlives-no-static, r=nikomats…
matthiaskrgr Jan 15, 2022
85c119c
Rollup merge of #92873 - eholk:async-symbol-names, r=tmandry
matthiaskrgr Jan 15, 2022
784e4ba
Rollup merge of #92879 - compiler-errors:into_iter_unsound, r=dtolnay
matthiaskrgr Jan 15, 2022
539175c
Rollup merge of #92892 - compiler-errors:const-param-env-for-const-bl…
matthiaskrgr Jan 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,12 +519,18 @@ fn push_unqualified_item_name(
output.push_str(tcx.crate_name(def_id.krate).as_str());
}
DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
let key = match tcx.generator_kind(def_id).unwrap() {
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block",
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure",
hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn",
hir::GeneratorKind::Gen => "generator",
};
// Generators look like closures, but we want to treat them differently
// in the debug info.
if cpp_like_debuginfo(tcx) {
write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
write!(output, "{}${}", key, disambiguated_data.disambiguator).unwrap();
} else {
write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
write!(output, "{{{}#{}}}", key, disambiguated_data.disambiguator).unwrap();
}
}
_ => match disambiguated_data.data.name() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let body = self.tcx.hir().body(anon_const.body);

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

let ty = fcx.check_expr_with_expectation(&body.value, expected);
Expand Down
94 changes: 48 additions & 46 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::outlives::obligations::TypeOutlives;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::{self, RegionckMode, SubregionOrigin};
use rustc_infer::infer::region_constraints::GenericKind;
use rustc_infer::infer::{self, RegionckMode};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::hir::map as hir_map;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
Expand Down Expand Up @@ -332,6 +333,12 @@ fn check_gat_where_clauses(
// outlives relationship (`Self: 'a`), then we want to ensure that is
// reflected in a where clause on the GAT itself.
for (region, region_idx) in &regions {
// Ignore `'static` lifetimes for the purpose of this lint: it's
// because we know it outlives everything and so doesn't give meaninful
// clues
if let ty::ReStatic = region {
continue;
}
for (ty, ty_idx) in &types {
// In our example, requires that Self: 'a
if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) {
Expand Down Expand Up @@ -371,10 +378,19 @@ fn check_gat_where_clauses(
// outlives relationship, then we want to ensure that is
// reflected in a where clause on the GAT itself.
for (region_a, region_a_idx) in &regions {
// Ignore `'static` lifetimes for the purpose of this lint: it's
// because we know it outlives everything and so doesn't give meaninful
// clues
if let ty::ReStatic = region_a {
continue;
}
for (region_b, region_b_idx) in &regions {
if region_a == region_b {
continue;
}
if let ty::ReStatic = region_b {
continue;
}

if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
debug!(?region_a_idx, ?region_b_idx);
Expand Down Expand Up @@ -502,8 +518,6 @@ fn check_gat_where_clauses(
}
}

// FIXME(jackh726): refactor some of the shared logic between the two functions below

/// Given a known `param_env` and a set of well formed types, can we prove that
/// `ty` outlives `region`.
fn ty_known_to_outlive<'tcx>(
Expand All @@ -514,54 +528,49 @@ fn ty_known_to_outlive<'tcx>(
ty: Ty<'tcx>,
region: ty::Region<'tcx>,
) -> bool {
// Unfortunately, we have to use a new `InferCtxt` each call, because
// region constraints get added and solved there and we need to test each
// call individually.
tcx.infer_ctxt().enter(|infcx| {
let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
outlives_environment.save_implied_bounds(id);
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();

let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);

let sup_type = ty;
let sub_region = region;

let origin = SubregionOrigin::from_obligation_cause(&cause, || {
infer::RelateParamBound(cause.span, sup_type, None)
});

resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
let outlives = &mut TypeOutlives::new(
&infcx,
infcx,
tcx,
&region_bound_pairs,
region_bound_pairs,
Some(infcx.tcx.lifetimes.re_root_empty),
param_env,
);
outlives.type_must_outlive(origin, sup_type, sub_region);

let errors = infcx.resolve_regions(
id.expect_owner().to_def_id(),
&outlives_environment,
RegionckMode::default(),
);

debug!(?errors, "errors");

// If we were able to prove that the type outlives the region without
// an error, it must be because of the implied or explicit bounds...
errors.is_empty()
outlives.type_must_outlive(origin, ty, region);
})
}

/// Given a known `param_env` and a set of well formed types, can we prove that
/// `region_a` outlives `region_b`
fn region_known_to_outlive<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
region_a: ty::Region<'tcx>,
region_b: ty::Region<'tcx>,
) -> bool {
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |mut infcx, _| {
use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
let origin = infer::RelateRegionParamBound(DUMMY_SP);
// `region_a: region_b` -> `region_b <= region_a`
infcx.push_sub_region_constraint(origin, region_b, region_a);
})
}

/// Given a known `param_env` and a set of well formed types, set up an
/// `InferCtxt`, call the passed function (to e.g. set up region constraints
/// to be tested), then resolve region and return errors
fn resolve_regions_with_wf_tys<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
add_constraints: impl for<'a> FnOnce(
&'a InferCtxt<'a, 'tcx>,
&'a Vec<(&'tcx ty::RegionKind, GenericKind<'tcx>)>,
),
) -> bool {
// Unfortunately, we have to use a new `InferCtxt` each call, because
// region constraints get added and solved there and we need to test each
Expand All @@ -570,16 +579,9 @@ fn region_known_to_outlive<'tcx>(
let mut outlives_environment = OutlivesEnvironment::new(param_env);
outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
outlives_environment.save_implied_bounds(id);
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();

let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);

let origin = SubregionOrigin::from_obligation_cause(&cause, || {
infer::RelateRegionParamBound(cause.span)
});

use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
// `region_a: region_b` -> `region_b <= region_a`
(&infcx).push_sub_region_constraint(origin, region_b, region_a);
add_constraints(&infcx, region_bound_pairs);

let errors = infcx.resolve_regions(
id.expect_owner().to_def_id(),
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/vec/into_iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: Sync, A: Allocator> Sync for IntoIter<T, A> {}
unsafe impl<T: Sync, A: Allocator + Sync> Sync for IntoIter<T, A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
Expand Down
21 changes: 6 additions & 15 deletions library/core/src/num/bignum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,24 +158,15 @@ macro_rules! define_bignum {
/// Returns the number of bits necessary to represent this value. Note that zero
/// is considered to need 0 bits.
pub fn bit_length(&self) -> usize {
// Skip over the most significant digits which are zero.
let digitbits = <$ty>::BITS as usize;
let digits = self.digits();
let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
let end = digits.len() - zeros;
let nonzero = &digits[..end];

if nonzero.is_empty() {
// Find the most significant non-zero digit.
let msd = digits.iter().rposition(|&x| x != 0);
match msd {
Some(msd) => msd * digitbits + digits[msd].log2() as usize + 1,
// There are no non-zero digits, i.e., the number is zero.
return 0;
}
// This could be optimized with leading_zeros() and bit shifts, but that's
// probably not worth the hassle.
let digitbits = <$ty>::BITS as usize;
let mut i = nonzero.len() * digitbits - 1;
while self.get_bit(i) == 0 {
i -= 1;
_ => 0,
}
i + 1
}

/// Adds `other` to itself and returns its own mutable reference.
Expand Down
35 changes: 35 additions & 0 deletions library/core/tests/num/bignum.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::num::bignum::tests::Big8x3 as Big;
use core::num::bignum::Big32x40;

#[test]
#[should_panic]
Expand Down Expand Up @@ -215,6 +216,16 @@ fn test_get_bit_out_of_range() {

#[test]
fn test_bit_length() {
for i in 0..8 * 3 {
// 010000...000
assert_eq!(Big::from_small(1).mul_pow2(i).bit_length(), i + 1);
}
for i in 1..8 * 3 - 1 {
// 010000...001
assert_eq!(Big::from_small(1).mul_pow2(i).add(&Big::from_small(1)).bit_length(), i + 1);
// 110000...000
assert_eq!(Big::from_small(3).mul_pow2(i).bit_length(), i + 2);
}
assert_eq!(Big::from_small(0).bit_length(), 0);
assert_eq!(Big::from_small(1).bit_length(), 1);
assert_eq!(Big::from_small(5).bit_length(), 3);
Expand All @@ -223,6 +234,30 @@ fn test_bit_length() {
assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
}

#[test]
fn test_bit_length_32x40() {
for i in 0..32 * 40 {
// 010000...000
assert_eq!(Big32x40::from_small(1).mul_pow2(i).bit_length(), i + 1);
}
for i in 1..32 * 40 - 1 {
// 010000...001
assert_eq!(
Big32x40::from_small(1).mul_pow2(i).add(&Big32x40::from_small(1)).bit_length(),
i + 1
);
// 110000...000
assert_eq!(Big32x40::from_small(3).mul_pow2(i).bit_length(), i + 2);
}
assert_eq!(Big32x40::from_small(0).bit_length(), 0);
assert_eq!(Big32x40::from_small(1).bit_length(), 1);
assert_eq!(Big32x40::from_small(5).bit_length(), 3);
assert_eq!(Big32x40::from_small(0x18).bit_length(), 5);
assert_eq!(Big32x40::from_u64(0x4073).bit_length(), 15);
assert_eq!(Big32x40::from_u64(0xffffff).bit_length(), 24);
assert_eq!(Big32x40::from_u64(0xffffffffffffffff).bit_length(), 64);
}

#[test]
fn test_ord() {
assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,14 +1031,14 @@ pub trait Read {
///
/// # use std::io;
/// fn main() -> io::Result<()> {
/// let stdin = io::read_to_string(&mut io::stdin())?;
/// let stdin = io::read_to_string(io::stdin())?;
/// println!("Stdin was:");
/// println!("{}", stdin);
/// Ok(())
/// }
/// ```
#[unstable(feature = "io_read_to_string", issue = "80218")]
pub fn read_to_string<R: Read>(reader: &mut R) -> Result<String> {
pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
let mut buf = String::new();
reader.read_to_string(&mut buf)?;
Ok(buf)
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/os/unix/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ pub trait OsStringExt: Sealed {

#[stable(feature = "rust1", since = "1.0.0")]
impl OsStringExt for OsString {
#[inline]
fn from_vec(vec: Vec<u8>) -> OsString {
FromInner::from_inner(Buf { inner: vec })
}
#[inline]
fn into_vec(self) -> Vec<u8> {
self.into_inner().inner
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/codegen/async-fn-debug-msvc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async fn async_fn_test() {
// FIXME: No way to reliably check the filename.

// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator$0"
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "async_fn$0"
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
// For brevity, we only check the struct name and members of the last variant.
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
Expand Down
2 changes: 1 addition & 1 deletion src/test/codegen/async-fn-debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async fn async_fn_test() {
// FIXME: No way to reliably check the filename.

// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{generator#0}", scope: [[ASYNC_FN]]
// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn#0}", scope: [[ASYNC_FN]]
// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
// CHECK-NOT: flags: DIFlagArtificial
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/consts/const-block-const-bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#![allow(unused)]
#![feature(const_fn_trait_bound, const_trait_impl, inline_const)]

const fn f<T: ~const Drop>(x: T) {}

struct UnconstDrop;

impl Drop for UnconstDrop {
fn drop(&mut self) {}
}

fn main() {
const {
f(UnconstDrop);
//~^ ERROR the trait bound `UnconstDrop: Drop` is not satisfied
}
}
21 changes: 21 additions & 0 deletions src/test/ui/consts/const-block-const-bound.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0277]: the trait bound `UnconstDrop: Drop` is not satisfied
--> $DIR/const-block-const-bound.rs:14:11
|
LL | f(UnconstDrop);
| - ^^^^^^^^^^^ the trait `Drop` is not implemented for `UnconstDrop`
| |
| required by a bound introduced by this call
|
note: required by a bound in `f`
--> $DIR/const-block-const-bound.rs:4:15
|
LL | const fn f<T: ~const Drop>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f`
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
|
LL | fn main() where UnconstDrop: Drop {
| +++++++++++++++++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
13 changes: 13 additions & 0 deletions src/test/ui/generic-associated-types/self-outlives-lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,17 @@ trait Trait: 'static {
fn make_assoc(_: &u32) -> Self::Assoc<'_>;
}

// We ignore `'static` lifetimes for any lints
trait StaticReturn<'a> {
type Y<'b>;
fn foo(&self) -> Self::Y<'static>;
}

// Same as above, but with extra method that takes GAT - just make sure this works
trait StaticReturnAndTakes<'a> {
type Y<'b>;
fn foo(&self) -> Self::Y<'static>;
fn bar<'b>(&self, arg: Self::Y<'b>);
}

fn main() {}