diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 9ecab82dd2e9..61322a6e556e 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -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() { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 14180526d846..faf3ef1e543c 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -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); diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 7c4f5d16abca..fbc446e3ea42 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -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; @@ -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 ®ions { + // 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) { @@ -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 ®ions { + // 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 ®ions { 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); @@ -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>( @@ -514,47 +528,21 @@ 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, - ®ion_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, @@ -562,6 +550,27 @@ fn region_known_to_outlive<'tcx>( wf_tys: &FxHashSet>, 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>, + 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 @@ -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(), diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 18e191f2b59a..f985fb78465b 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -125,7 +125,7 @@ impl AsRef<[T]> for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for IntoIter {} +unsafe impl Sync for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 8a06a0988829..98d8a8a1d74a 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -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. diff --git a/library/core/tests/num/bignum.rs b/library/core/tests/num/bignum.rs index 1457064cc8d5..416e7cea7a67 100644 --- a/library/core/tests/num/bignum.rs +++ b/library/core/tests/num/bignum.rs @@ -1,4 +1,5 @@ use core::num::bignum::tests::Big8x3 as Big; +use core::num::bignum::Big32x40; #[test] #[should_panic] @@ -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); @@ -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)); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 358ef22e708d..824938ce38e6 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -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(reader: &mut R) -> Result { +pub fn read_to_string(mut reader: R) -> Result { let mut buf = String::new(); reader.read_to_string(&mut buf)?; Ok(buf) diff --git a/library/std/src/os/unix/ffi/os_str.rs b/library/std/src/os/unix/ffi/os_str.rs index 54c9a9382f22..650f712bc6ee 100644 --- a/library/std/src/os/unix/ffi/os_str.rs +++ b/library/std/src/os/unix/ffi/os_str.rs @@ -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) -> OsString { FromInner::from_inner(Buf { inner: vec }) } + #[inline] fn into_vec(self) -> Vec { self.into_inner().inner } diff --git a/src/llvm-project b/src/llvm-project index 6b3dbcc81a47..2abffbf977a9 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 6b3dbcc81a470e5da84576d63fcfc19e3b1154cd +Subproject commit 2abffbf977a9e8c6ca4174a08fe5c4d7781f0aac diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index 0c16b9ad3ab5..bb0db9d3d851 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -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, diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs index 39319a3ea722..f456f7ffc0fb 100644 --- a/src/test/codegen/async-fn-debug.rs +++ b/src/test/codegen/async-fn-debug.rs @@ -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]*]] diff --git a/src/test/ui/consts/const-block-const-bound.rs b/src/test/ui/consts/const-block-const-bound.rs new file mode 100644 index 000000000000..3bfc759a9aef --- /dev/null +++ b/src/test/ui/consts/const-block-const-bound.rs @@ -0,0 +1,17 @@ +#![allow(unused)] +#![feature(const_fn_trait_bound, const_trait_impl, inline_const)] + +const fn f(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 + } +} diff --git a/src/test/ui/consts/const-block-const-bound.stderr b/src/test/ui/consts/const-block-const-bound.stderr new file mode 100644 index 000000000000..0e6e426e7c2c --- /dev/null +++ b/src/test/ui/consts/const-block-const-bound.stderr @@ -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(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`. diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs index 37b3a6155d5a..fcc53b4ede0c 100644 --- a/src/test/ui/generic-associated-types/self-outlives-lint.rs +++ b/src/test/ui/generic-associated-types/self-outlives-lint.rs @@ -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() {}