Skip to content

Commit 9f8f0a6

Browse files
committed
Auto merge of #94357 - matthiaskrgr:rollup-xrjaof3, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #93845 (Remove in band lifetimes) - #94155 (Extend toggle GUI test a bit) - #94252 (don't special case `DefKind::Ctor` in encoding) - #94305 (Remove an unnecessary restriction in `dest_prop`) - #94343 (Miri fn ptr check: don't use conservative null check) - #94344 (diagnostic: suggest parens when users want logical ops, but get closures) - #94352 (Fix SGX docs build) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9b2a465 + 6060645 commit 9f8f0a6

File tree

96 files changed

+386
-1660
lines changed

Some content is hidden

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

96 files changed

+386
-1660
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+12-45
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,9 @@ struct LoweringContext<'a, 'hir: 'a> {
142142
/// indicate whether or not we're in a place where new lifetimes will result
143143
/// in in-band lifetime definitions, such a function or an impl header,
144144
/// including implicit lifetimes from `impl_header_lifetime_elision`.
145-
is_collecting_in_band_lifetimes: bool,
145+
is_collecting_anonymous_lifetimes: bool,
146146

147147
/// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
148-
/// When `is_collecting_in_band_lifetimes` is true, each lifetime is checked
149-
/// against this list to see if it is already in-scope, or if a definition
150-
/// needs to be created for it.
151-
///
152148
/// We always store a `normalize_to_macros_2_0()` version of the param-name in this
153149
/// vector.
154150
in_scope_lifetimes: Vec<ParamName>,
@@ -379,7 +375,7 @@ pub fn lower_crate<'a, 'hir>(
379375
task_context: None,
380376
current_item: None,
381377
lifetimes_to_define: Vec::new(),
382-
is_collecting_in_band_lifetimes: false,
378+
is_collecting_anonymous_lifetimes: false,
383379
in_scope_lifetimes: Vec::new(),
384380
allow_try_trait: Some([sym::try_trait_v2][..].into()),
385381
allow_gen_future: Some([sym::gen_future][..].into()),
@@ -726,13 +722,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
726722
&mut self,
727723
f: impl FnOnce(&mut Self) -> T,
728724
) -> (Vec<(Span, ParamName)>, T) {
729-
let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true);
725+
let was_collecting = std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, true);
730726
let len = self.lifetimes_to_define.len();
731727

732728
let res = f(self);
733729

734730
let lifetimes_to_define = self.lifetimes_to_define.split_off(len);
735-
self.is_collecting_in_band_lifetimes = was_collecting;
731+
self.is_collecting_anonymous_lifetimes = was_collecting;
736732
(lifetimes_to_define, res)
737733
}
738734

@@ -749,7 +745,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
749745
// that collisions are ok here and this shouldn't
750746
// really show up for end-user.
751747
let (str_name, kind) = match hir_name {
752-
ParamName::Plain(ident) => (ident.name, hir::LifetimeParamKind::InBand),
748+
ParamName::Plain(ident) => (ident.name, hir::LifetimeParamKind::Explicit),
753749
ParamName::Fresh(_) => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Elided),
754750
ParamName::Error => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Error),
755751
};
@@ -773,38 +769,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
773769
}
774770
}
775771

776-
/// When there is a reference to some lifetime `'a`, and in-band
777-
/// lifetimes are enabled, then we want to push that lifetime into
778-
/// the vector of names to define later. In that case, it will get
779-
/// added to the appropriate generics.
780-
fn maybe_collect_in_band_lifetime(&mut self, ident: Ident) {
781-
if !self.is_collecting_in_band_lifetimes {
782-
return;
783-
}
784-
785-
if !self.sess.features_untracked().in_band_lifetimes {
786-
return;
787-
}
788-
789-
if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.normalize_to_macros_2_0())) {
790-
return;
791-
}
792-
793-
let hir_name = ParamName::Plain(ident);
794-
795-
if self.lifetimes_to_define.iter().any(|(_, lt_name)| {
796-
lt_name.normalize_to_macros_2_0() == hir_name.normalize_to_macros_2_0()
797-
}) {
798-
return;
799-
}
800-
801-
self.lifetimes_to_define.push((ident.span, hir_name));
802-
}
803-
804772
/// When we have either an elided or `'_` lifetime in an impl
805773
/// header, we convert it to an in-band lifetime.
806-
fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName {
807-
assert!(self.is_collecting_in_band_lifetimes);
774+
fn collect_fresh_anonymous_lifetime(&mut self, span: Span) -> ParamName {
775+
assert!(self.is_collecting_anonymous_lifetimes);
808776
let index = self.lifetimes_to_define.len() + self.in_scope_lifetimes.len();
809777
let hir_name = ParamName::Fresh(index);
810778
self.lifetimes_to_define.push((span, hir_name));
@@ -1946,7 +1914,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19461914
}
19471915
ident if ident.name == kw::UnderscoreLifetime => match self.anonymous_lifetime_mode {
19481916
AnonymousLifetimeMode::CreateParameter => {
1949-
let fresh_name = self.collect_fresh_in_band_lifetime(span);
1917+
let fresh_name = self.collect_fresh_anonymous_lifetime(span);
19501918
self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name))
19511919
}
19521920

@@ -1957,7 +1925,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19571925
AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span),
19581926
},
19591927
ident => {
1960-
self.maybe_collect_in_band_lifetime(ident);
19611928
let param_name = ParamName::Plain(self.lower_ident(ident));
19621929
self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name))
19631930
}
@@ -2001,8 +1968,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20011968

20021969
let (name, kind) = match param.kind {
20031970
GenericParamKind::Lifetime => {
2004-
let was_collecting_in_band = self.is_collecting_in_band_lifetimes;
2005-
self.is_collecting_in_band_lifetimes = false;
1971+
let was_collecting_in_band = self.is_collecting_anonymous_lifetimes;
1972+
self.is_collecting_anonymous_lifetimes = false;
20061973

20071974
let lt = self
20081975
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
@@ -2025,7 +1992,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20251992
let kind =
20261993
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
20271994

2028-
self.is_collecting_in_band_lifetimes = was_collecting_in_band;
1995+
self.is_collecting_anonymous_lifetimes = was_collecting_in_band;
20291996

20301997
(param_name, kind)
20311998
}
@@ -2384,7 +2351,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23842351
// Hence `impl Foo for &u32` becomes `impl<'f> Foo for &'f u32` for some fresh
23852352
// `'f`.
23862353
AnonymousLifetimeMode::CreateParameter => {
2387-
let fresh_name = self.collect_fresh_in_band_lifetime(span);
2354+
let fresh_name = self.collect_fresh_anonymous_lifetime(span);
23882355
hir::Lifetime {
23892356
hir_id: self.next_id(),
23902357
span: self.lower_span(span),

compiler/rustc_const_eval/src/const_eval/machine.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,9 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
217217
// Comparisons of abstract pointers with null pointers are known if the pointer
218218
// is in bounds, because if they are in bounds, the pointer can't be null.
219219
// Inequality with integers other than null can never be known for sure.
220-
(Scalar::Int(int), Scalar::Ptr(ptr, _)) | (Scalar::Ptr(ptr, _), Scalar::Int(int)) => {
221-
int.is_null() && !self.memory.ptr_may_be_null(ptr.into())
220+
(Scalar::Int(int), ptr @ Scalar::Ptr(..))
221+
| (ptr @ Scalar::Ptr(..), Scalar::Int(int)) => {
222+
int.is_null() && !self.scalar_may_be_null(ptr)
222223
}
223224
// FIXME: return `true` for at least some comparisons where we can reliably
224225
// determine the result of runtime inequality tests at compile-time.

compiler/rustc_const_eval/src/interpret/eval_context.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use rustc_span::{Pos, Span};
2222
use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
2323

2424
use super::{
25-
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
26-
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar,
27-
ScalarMaybeUninit, StackPopJump,
25+
AllocCheck, AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine,
26+
MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance,
27+
Scalar, ScalarMaybeUninit, StackPopJump,
2828
};
2929
use crate::transform::validate::equal_up_to_regions;
3030

@@ -440,6 +440,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
440440
self.memory.scalar_to_ptr(scalar)
441441
}
442442

443+
/// Test if this value might be null.
444+
/// If the machine does not support ptr-to-int casts, this is conservative.
445+
pub fn scalar_may_be_null(&self, scalar: Scalar<M::PointerTag>) -> bool {
446+
match scalar.try_to_int() {
447+
Ok(int) => int.is_null(),
448+
Err(_) => {
449+
let ptr = self.scalar_to_ptr(scalar);
450+
match self.memory.ptr_try_get_alloc(ptr) {
451+
Ok((alloc_id, offset, _)) => {
452+
let (size, _align) = self
453+
.memory
454+
.get_size_and_align(alloc_id, AllocCheck::MaybeDead)
455+
.expect("alloc info with MaybeDead cannot fail");
456+
// If the pointer is out-of-bounds, it may be null.
457+
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
458+
offset > size
459+
}
460+
Err(offset) => offset == 0,
461+
}
462+
}
463+
}
464+
}
465+
443466
/// Call this to turn untagged "global" pointers (obtained via `tcx`) into
444467
/// the machine pointer to the allocation. Must never be used
445468
/// for any other pointers, nor for TLS statics.

compiler/rustc_const_eval/src/interpret/memory.rs

-15
Original file line numberDiff line numberDiff line change
@@ -483,21 +483,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
483483
}
484484
})
485485
}
486-
487-
/// Test if the pointer might be null.
488-
pub fn ptr_may_be_null(&self, ptr: Pointer<Option<M::PointerTag>>) -> bool {
489-
match self.ptr_try_get_alloc(ptr) {
490-
Ok((alloc_id, offset, _)) => {
491-
let (size, _align) = self
492-
.get_size_and_align(alloc_id, AllocCheck::MaybeDead)
493-
.expect("alloc info with MaybeDead cannot fail");
494-
// If the pointer is out-of-bounds, it may be null.
495-
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
496-
offset > size
497-
}
498-
Err(offset) => offset == 0,
499-
}
500-
}
501486
}
502487

503488
/// Allocation accessors

compiler/rustc_const_eval/src/interpret/operand.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -720,12 +720,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
720720
Err(dbg_val) => {
721721
// So this is a pointer then, and casting to an int failed.
722722
// Can only happen during CTFE.
723-
let ptr = self.scalar_to_ptr(tag_val);
724723
// The niche must be just 0, and the ptr not null, then we know this is
725724
// okay. Everything else, we conservatively reject.
726725
let ptr_valid = niche_start == 0
727726
&& variants_start == variants_end
728-
&& !self.memory.ptr_may_be_null(ptr);
727+
&& !self.scalar_may_be_null(tag_val);
729728
if !ptr_valid {
730729
throw_ub!(InvalidTag(dbg_val))
731730
}

compiler/rustc_const_eval/src/interpret/validity.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -572,21 +572,25 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
572572
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
573573
err_ub!(InvalidUninitBytes(None)) => { "uninitialized bytes" } expected { "a proper pointer or integer value" },
574574
);
575-
let ptr = self.ecx.scalar_to_ptr(value);
576-
// Ensure the pointer is non-null.
577-
if self.ecx.memory.ptr_may_be_null(ptr) {
578-
throw_validation_failure!(self.path, { "a potentially null function pointer" });
579-
}
575+
580576
// If we check references recursively, also check that this points to a function.
581577
if let Some(_) = self.ref_tracking {
578+
let ptr = self.ecx.scalar_to_ptr(value);
582579
let _fn = try_validation!(
583580
self.ecx.memory.get_fn(ptr),
584581
self.path,
582+
err_ub!(DanglingIntPointer(0, _)) =>
583+
{ "a null function pointer" },
585584
err_ub!(DanglingIntPointer(..)) |
586585
err_ub!(InvalidFunctionPointer(..)) =>
587586
{ "{:x}", value } expected { "a function pointer" },
588587
);
589588
// FIXME: Check if the signature matches
589+
} else {
590+
// Otherwise (for standalone Miri), we have to still check it to be non-null.
591+
if self.ecx.scalar_may_be_null(value) {
592+
throw_validation_failure!(self.path, { "a null function pointer" });
593+
}
590594
}
591595
Ok(true)
592596
}
@@ -644,10 +648,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
644648
Err(_) => {
645649
// So this is a pointer then, and casting to an int failed.
646650
// Can only happen during CTFE.
647-
let ptr = self.ecx.scalar_to_ptr(value);
648651
if start == 1 && end == max_value {
649652
// Only null is the niche. So make sure the ptr is NOT null.
650-
if self.ecx.memory.ptr_may_be_null(ptr) {
653+
if self.ecx.scalar_may_be_null(value) {
651654
throw_validation_failure!(self.path,
652655
{ "a potentially null pointer" }
653656
expected {
@@ -758,7 +761,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
758761
fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
759762
trace!("visit_value: {:?}, {:?}", *op, op.layout);
760763

761-
// Check primitive types -- the leafs of our recursive descend.
764+
// Check primitive types -- the leaves of our recursive descent.
762765
if self.try_visit_primitive(op)? {
763766
return Ok(());
764767
}

compiler/rustc_error_codes/src/error_codes/E0687.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
In-band lifetimes cannot be used in `fn`/`Fn` syntax.
24

35
Erroneous code examples:
46

5-
```compile_fail,E0687
7+
```ignore (feature got removed)
68
#![feature(in_band_lifetimes)]
79
810
fn foo(x: fn(&'a u32)) {} // error!

compiler/rustc_error_codes/src/error_codes/E0688.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
In-band lifetimes were mixed with explicit lifetime binders.
24

35
Erroneous code example:
46

5-
```compile_fail,E0688
7+
```ignore (feature got removed)
68
#![feature(in_band_lifetimes)]
79
810
fn foo<'a>(x: &'a u32, y: &'b u32) {} // error!

compiler/rustc_feature/src/active.rs

-2
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,6 @@ declare_features! (
400400
(active, if_let_guard, "1.47.0", Some(51114), None),
401401
/// Allows using imported `main` function
402402
(active, imported_main, "1.53.0", Some(28937), None),
403-
/// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
404-
(active, in_band_lifetimes, "1.23.0", Some(44524), None),
405403
/// Allows inferring `'static` outlives requirements (RFC 2093).
406404
(active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
407405
/// Allows associated types in inherent impls.

compiler/rustc_feature/src/removed.rs

+3
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ declare_features! (
104104
(removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
105105
Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
106106
(removed, import_shadowing, "1.0.0", None, None, None),
107+
/// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
108+
(removed, in_band_lifetimes, "1.23.0", Some(44524), None,
109+
Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")),
107110
/// Lazily evaluate constants. This allows constants to depend on type parameters.
108111
(removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")),
109112
/// Allows using the `#[link_args]` attribute.

compiler/rustc_hir/src/hir.rs

-5
Original file line numberDiff line numberDiff line change
@@ -471,11 +471,6 @@ pub enum LifetimeParamKind {
471471
// `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
472472
Explicit,
473473

474-
// Indicates that the lifetime definition was synthetically added
475-
// as a result of an in-band lifetime usage (e.g., in
476-
// `fn foo(x: &'a u8) -> &'a u8 { x }`).
477-
InBand,
478-
479474
// Indication that the lifetime was elided (e.g., in both cases in
480475
// `fn foo(x: &u8) -> &'_ u8 { x }`).
481476
Elided,

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
125125
// Find the index of the named region that was part of the
126126
// error. We will then search the function parameters for a bound
127127
// region at the right depth with the same index
128-
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
128+
(Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
129129
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
130130
if id == def_id {
131131
self.found_type = Some(arg);
@@ -137,7 +137,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
137137
// error. We will then search the function parameters for a bound
138138
// region at the right depth with the same index
139139
(
140-
Some(rl::Region::LateBound(debruijn_index, _, id, _)),
140+
Some(rl::Region::LateBound(debruijn_index, _, id)),
141141
ty::BrNamed(def_id, _),
142142
) => {
143143
debug!(
@@ -155,8 +155,8 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
155155
Some(
156156
rl::Region::Static
157157
| rl::Region::Free(_, _)
158-
| rl::Region::EarlyBound(_, _, _)
159-
| rl::Region::LateBound(_, _, _, _)
158+
| rl::Region::EarlyBound(_, _)
159+
| rl::Region::LateBound(_, _, _)
160160
| rl::Region::LateBoundAnon(_, _, _),
161161
)
162162
| None,
@@ -221,15 +221,15 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
221221
}
222222
}
223223

224-
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
224+
(Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
225225
debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
226226
if id == def_id {
227227
self.found_it = true;
228228
return; // we can stop visiting now
229229
}
230230
}
231231

232-
(Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _)) => {
232+
(Some(rl::Region::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
233233
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
234234
debug!("id={:?}", id);
235235
debug!("def_id={:?}", def_id);
@@ -242,8 +242,8 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
242242
(
243243
Some(
244244
rl::Region::Static
245-
| rl::Region::EarlyBound(_, _, _)
246-
| rl::Region::LateBound(_, _, _, _)
245+
| rl::Region::EarlyBound(_, _)
246+
| rl::Region::LateBound(_, _, _)
247247
| rl::Region::LateBoundAnon(_, _, _)
248248
| rl::Region::Free(_, _),
249249
)

0 commit comments

Comments
 (0)