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
This commit is contained in:
commit
b13a5bf3c4
14 changed files with 173 additions and 86 deletions
|
@ -519,12 +519,18 @@ fn push_unqualified_item_name(
|
||||||
output.push_str(tcx.crate_name(def_id.krate).as_str());
|
output.push_str(tcx.crate_name(def_id.krate).as_str());
|
||||||
}
|
}
|
||||||
DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => {
|
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
|
// Generators look like closures, but we want to treat them differently
|
||||||
// in the debug info.
|
// in the debug info.
|
||||||
if cpp_like_debuginfo(tcx) {
|
if cpp_like_debuginfo(tcx) {
|
||||||
write!(output, "generator${}", disambiguated_data.disambiguator).unwrap();
|
write!(output, "{}${}", key, disambiguated_data.disambiguator).unwrap();
|
||||||
} else {
|
} else {
|
||||||
write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap();
|
write!(output, "{{{}#{}}}", key, disambiguated_data.disambiguator).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => match disambiguated_data.data.name() {
|
_ => match disambiguated_data.data.name() {
|
||||||
|
|
|
@ -1226,7 +1226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let body = self.tcx.hir().body(anon_const.body);
|
let body = self.tcx.hir().body(anon_const.body);
|
||||||
|
|
||||||
// Create a new function context.
|
// 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);
|
crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
|
||||||
|
|
||||||
let ty = fcx.check_expr_with_expectation(&body.value, expected);
|
let ty = fcx.check_expr_with_expectation(&body.value, expected);
|
||||||
|
|
|
@ -14,8 +14,9 @@ use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::ItemKind;
|
use rustc_hir::ItemKind;
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::outlives::obligations::TypeOutlives;
|
use rustc_infer::infer::outlives::obligations::TypeOutlives;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::region_constraints::GenericKind;
|
||||||
use rustc_infer::infer::{self, RegionckMode, SubregionOrigin};
|
use rustc_infer::infer::{self, RegionckMode};
|
||||||
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_middle::hir::map as hir_map;
|
use rustc_middle::hir::map as hir_map;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
|
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
|
||||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
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
|
// outlives relationship (`Self: 'a`), then we want to ensure that is
|
||||||
// reflected in a where clause on the GAT itself.
|
// reflected in a where clause on the GAT itself.
|
||||||
for (region, region_idx) in ®ions {
|
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 {
|
for (ty, ty_idx) in &types {
|
||||||
// In our example, requires that Self: 'a
|
// In our example, requires that Self: 'a
|
||||||
if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) {
|
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
|
// outlives relationship, then we want to ensure that is
|
||||||
// reflected in a where clause on the GAT itself.
|
// reflected in a where clause on the GAT itself.
|
||||||
for (region_a, region_a_idx) in ®ions {
|
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 {
|
for (region_b, region_b_idx) in ®ions {
|
||||||
if region_a == region_b {
|
if region_a == region_b {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if let ty::ReStatic = region_b {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
|
if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
|
||||||
debug!(?region_a_idx, ?region_b_idx);
|
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
|
/// Given a known `param_env` and a set of well formed types, can we prove that
|
||||||
/// `ty` outlives `region`.
|
/// `ty` outlives `region`.
|
||||||
fn ty_known_to_outlive<'tcx>(
|
fn ty_known_to_outlive<'tcx>(
|
||||||
|
@ -513,6 +527,50 @@ fn ty_known_to_outlive<'tcx>(
|
||||||
wf_tys: &FxHashSet<Ty<'tcx>>,
|
wf_tys: &FxHashSet<Ty<'tcx>>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
region: ty::Region<'tcx>,
|
region: ty::Region<'tcx>,
|
||||||
|
) -> bool {
|
||||||
|
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,
|
||||||
|
tcx,
|
||||||
|
region_bound_pairs,
|
||||||
|
Some(infcx.tcx.lifetimes.re_root_empty),
|
||||||
|
param_env,
|
||||||
|
);
|
||||||
|
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 {
|
) -> bool {
|
||||||
// Unfortunately, we have to use a new `InferCtxt` each call, because
|
// Unfortunately, we have to use a new `InferCtxt` each call, because
|
||||||
// region constraints get added and solved there and we need to test each
|
// region constraints get added and solved there and we need to test each
|
||||||
|
@ -523,63 +581,7 @@ fn ty_known_to_outlive<'tcx>(
|
||||||
outlives_environment.save_implied_bounds(id);
|
outlives_environment.save_implied_bounds(id);
|
||||||
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
|
let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
|
||||||
|
|
||||||
let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
|
add_constraints(&infcx, region_bound_pairs);
|
||||||
|
|
||||||
let sup_type = ty;
|
|
||||||
let sub_region = region;
|
|
||||||
|
|
||||||
let origin = SubregionOrigin::from_obligation_cause(&cause, || {
|
|
||||||
infer::RelateParamBound(cause.span, sup_type, None)
|
|
||||||
});
|
|
||||||
|
|
||||||
let outlives = &mut TypeOutlives::new(
|
|
||||||
&infcx,
|
|
||||||
tcx,
|
|
||||||
®ion_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()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
// 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 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);
|
|
||||||
|
|
||||||
let errors = infcx.resolve_regions(
|
let errors = infcx.resolve_regions(
|
||||||
id.expect_owner().to_def_id(),
|
id.expect_owner().to_def_id(),
|
||||||
|
|
|
@ -125,7 +125,7 @@ impl<T, A: Allocator> AsRef<[T]> for IntoIter<T, A> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
|
unsafe impl<T: Send, A: Allocator + Send> Send for IntoIter<T, A> {}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
|
||||||
|
|
|
@ -158,24 +158,15 @@ macro_rules! define_bignum {
|
||||||
/// Returns the number of bits necessary to represent this value. Note that zero
|
/// Returns the number of bits necessary to represent this value. Note that zero
|
||||||
/// is considered to need 0 bits.
|
/// is considered to need 0 bits.
|
||||||
pub fn bit_length(&self) -> usize {
|
pub fn bit_length(&self) -> usize {
|
||||||
// Skip over the most significant digits which are zero.
|
|
||||||
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() {
|
|
||||||
// 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 digitbits = <$ty>::BITS as usize;
|
||||||
let mut i = nonzero.len() * digitbits - 1;
|
let digits = self.digits();
|
||||||
while self.get_bit(i) == 0 {
|
// Find the most significant non-zero digit.
|
||||||
i -= 1;
|
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.
|
||||||
|
_ => 0,
|
||||||
}
|
}
|
||||||
i + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds `other` to itself and returns its own mutable reference.
|
/// Adds `other` to itself and returns its own mutable reference.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use core::num::bignum::tests::Big8x3 as Big;
|
use core::num::bignum::tests::Big8x3 as Big;
|
||||||
|
use core::num::bignum::Big32x40;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
|
@ -215,6 +216,16 @@ fn test_get_bit_out_of_range() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bit_length() {
|
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(0).bit_length(), 0);
|
||||||
assert_eq!(Big::from_small(1).bit_length(), 1);
|
assert_eq!(Big::from_small(1).bit_length(), 1);
|
||||||
assert_eq!(Big::from_small(5).bit_length(), 3);
|
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);
|
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]
|
#[test]
|
||||||
fn test_ord() {
|
fn test_ord() {
|
||||||
assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
|
assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
|
||||||
|
|
|
@ -1031,14 +1031,14 @@ pub trait Read {
|
||||||
///
|
///
|
||||||
/// # use std::io;
|
/// # use std::io;
|
||||||
/// fn main() -> io::Result<()> {
|
/// 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 was:");
|
||||||
/// println!("{}", stdin);
|
/// println!("{}", stdin);
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "io_read_to_string", issue = "80218")]
|
#[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();
|
let mut buf = String::new();
|
||||||
reader.read_to_string(&mut buf)?;
|
reader.read_to_string(&mut buf)?;
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
|
|
|
@ -28,9 +28,11 @@ pub trait OsStringExt: Sealed {
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl OsStringExt for OsString {
|
impl OsStringExt for OsString {
|
||||||
|
#[inline]
|
||||||
fn from_vec(vec: Vec<u8>) -> OsString {
|
fn from_vec(vec: Vec<u8>) -> OsString {
|
||||||
FromInner::from_inner(Buf { inner: vec })
|
FromInner::from_inner(Buf { inner: vec })
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
fn into_vec(self) -> Vec<u8> {
|
fn into_vec(self) -> Vec<u8> {
|
||||||
self.into_inner().inner
|
self.into_inner().inner
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6b3dbcc81a470e5da84576d63fcfc19e3b1154cd
|
Subproject commit 2abffbf977a9e8c6ca4174a08fe5c4d7781f0aac
|
|
@ -17,7 +17,7 @@ async fn async_fn_test() {
|
||||||
// FIXME: No way to reliably check the filename.
|
// FIXME: No way to reliably check the filename.
|
||||||
|
|
||||||
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
|
// 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]],
|
// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
|
||||||
// For brevity, we only check the struct name and members of the last variant.
|
// For brevity, we only check the struct name and members of the last variant.
|
||||||
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
|
// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
|
||||||
|
|
|
@ -17,7 +17,7 @@ async fn async_fn_test() {
|
||||||
// FIXME: No way to reliably check the filename.
|
// FIXME: No way to reliably check the filename.
|
||||||
|
|
||||||
// CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
|
// 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: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]],
|
||||||
// CHECK-NOT: flags: DIFlagArtificial
|
// CHECK-NOT: flags: DIFlagArtificial
|
||||||
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
|
// CHECK-SAME: discriminator: [[DISC:![0-9]*]]
|
||||||
|
|
17
src/test/ui/consts/const-block-const-bound.rs
Normal file
17
src/test/ui/consts/const-block-const-bound.rs
Normal file
|
@ -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
src/test/ui/consts/const-block-const-bound.stderr
Normal file
21
src/test/ui/consts/const-block-const-bound.stderr
Normal file
|
@ -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`.
|
|
@ -189,4 +189,17 @@ trait Trait: 'static {
|
||||||
fn make_assoc(_: &u32) -> Self::Assoc<'_>;
|
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() {}
|
fn main() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue