Skip to content

Commit

Permalink
Auto merge of #112702 - Dylan-DPC:rollup-12d6qay, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #112163 (fix: inline `predicate_may_hold_fatal` and remove expect call in it)
 - #112399 (Instantiate closure synthetic substs in root universe)
 - #112443 (Opportunistically resolve regions in new solver)
 - #112535 (reorder attributes to make miri-test-libstd work again)
 - #112579 (Fix building libstd documentation on FreeBSD.)
 - #112639 (Fix `dead_code_cgu` computation)
 - #112642 (Handle interpolated literal errors)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 16, 2023
2 parents 99b3346 + c2e1097 commit 2304917
Show file tree
Hide file tree
Showing 18 changed files with 207 additions and 88 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.typeck_root_def_id(expr_def_id.to_def_id()),
);

let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin {
let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: self.tcx.def_span(expr_def_id),
});
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
None => self.next_ty_var(TypeVariableOrigin {
None => self.next_root_ty_var(TypeVariableOrigin {
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn errors_reported_since_creation(&self) -> bool {
self.tcx.sess.err_count() > self.err_count_on_creation
}

pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT))
}
}

impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
Expand Down
41 changes: 33 additions & 8 deletions compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> {
}

pub fn is_identity_modulo_regions(&self) -> bool {
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
ty::GenericArgKind::Lifetime(_) => true,
ty::GenericArgKind::Type(ty) => {
matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
}
ty::GenericArgKind::Const(ct) => {
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
let mut var = ty::BoundVar::from_u32(0);
for arg in self.var_values {
match arg.unpack() {
ty::GenericArgKind::Lifetime(r) => {
if let ty::ReLateBound(ty::INNERMOST, br) = *r
&& var == br.var
{
var = var + 1;
} else {
// It's ok if this region var isn't unique
}
},
ty::GenericArgKind::Type(ty) => {
if let ty::Bound(ty::INNERMOST, bt) = *ty.kind()
&& var == bt.var
{
var = var + 1;
} else {
return false;
}
}
ty::GenericArgKind::Const(ct) => {
if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind()
&& var == bc
{
var = var + 1;
} else {
return false;
}
}
}
})
}

true
}
}

Expand Down
85 changes: 41 additions & 44 deletions compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,14 +155,16 @@ where
// functions and statics defined in the local crate.
let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
place_root_mono_items(cx, mono_items)
};
let mut placed = place_root_mono_items(cx, mono_items);

for cgu in &mut codegen_units {
cgu.create_size_estimate(tcx);
}
for cgu in &mut placed.codegen_units {
cgu.create_size_estimate(tcx);
}

debug_dump(tcx, "ROOTS", &codegen_units, unique_inlined_stats);
debug_dump(tcx, "ROOTS", &placed.codegen_units, placed.unique_inlined_stats);

placed
};

// Merge until we have at most `max_cgu_count` codegen units.
// `merge_codegen_units` is responsible for updating the CGU size
Expand All @@ -179,59 +181,34 @@ where
// local functions the definition of which is marked with `#[inline]`.
{
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
place_inlined_mono_items(cx, &mut codegen_units)
};
place_inlined_mono_items(cx, &mut codegen_units);

for cgu in &mut codegen_units {
cgu.create_size_estimate(tcx);
}
for cgu in &mut codegen_units {
cgu.create_size_estimate(tcx);
}

debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats);
debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats);
}

// Next we try to make as many symbols "internal" as possible, so LLVM has
// more freedom to optimize.
if !tcx.sess.link_dead_code() {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
internalize_symbols(cx, &mut codegen_units, internalization_candidates);

debug_dump(tcx, "INTERNALIZE", &codegen_units, unique_inlined_stats);
}

// Mark one CGU for dead code, if necessary.
let instrument_dead_code =
tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions();

if instrument_dead_code {
assert!(
codegen_units.len() > 0,
"There must be at least one CGU that code coverage data can be generated in."
);

// Find the smallest CGU that has exported symbols and put the dead
// function stubs in that CGU. We look for exported symbols to increase
// the likelihood the linker won't throw away the dead functions.
// FIXME(#92165): In order to truly resolve this, we need to make sure
// the object file (CGU) containing the dead function stubs is included
// in the final binary. This will probably require forcing these
// function symbols to be included via `-u` or `/include` linker args.
let mut cgus: Vec<_> = codegen_units.iter_mut().collect();
cgus.sort_by_key(|cgu| cgu.size_estimate());

let dead_code_cgu =
if let Some(cgu) = cgus.into_iter().rev().find(|cgu| {
cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)
}) {
cgu
} else {
// If there are no CGUs that have externally linked items,
// then we just pick the first CGU as a fallback.
&mut codegen_units[0]
};
dead_code_cgu.make_code_coverage_dead_code_cgu();
mark_code_coverage_dead_code_cgu(&mut codegen_units);
}

// Ensure CGUs are sorted by name, so that we get deterministic results.
assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str()))));

debug_dump(tcx, "FINAL", &codegen_units, unique_inlined_stats);

codegen_units
}

Expand Down Expand Up @@ -363,9 +340,7 @@ fn merge_codegen_units<'tcx>(

// Move the mono-items from `smallest` to `second_smallest`
second_smallest.modify_size_estimate(smallest.size_estimate());
for (k, v) in smallest.items_mut().drain() {
second_smallest.items_mut().insert(k, v);
}
second_smallest.items_mut().extend(smallest.items_mut().drain());

// Record that `second_smallest` now contains all the stuff that was
// in `smallest` before.
Expand Down Expand Up @@ -545,6 +520,28 @@ fn internalize_symbols<'tcx>(
}
}

fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx>]) {
assert!(!codegen_units.is_empty());

// Find the smallest CGU that has exported symbols and put the dead
// function stubs in that CGU. We look for exported symbols to increase
// the likelihood the linker won't throw away the dead functions.
// FIXME(#92165): In order to truly resolve this, we need to make sure
// the object file (CGU) containing the dead function stubs is included
// in the final binary. This will probably require forcing these
// function symbols to be included via `-u` or `/include` linker args.
let dead_code_cgu = codegen_units
.iter_mut()
.filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External))
.min_by_key(|cgu| cgu.size_estimate());

// If there are no CGUs that have externally linked items, then we just
// pick the first CGU as a fallback.
let dead_code_cgu = if let Some(cgu) = dead_code_cgu { cgu } else { &mut codegen_units[0] };

dead_code_cgu.make_code_coverage_dead_code_cgu();
}

fn characteristic_def_id_of_mono_item<'tcx>(
tcx: TyCtxt<'tcx>,
mono_item: MonoItem<'tcx>,
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2023,17 +2023,14 @@ impl<'a> Parser<'a> {
let recovered = self.recover_after_dot();
let token = recovered.as_ref().unwrap_or(&self.token);
match token::Lit::from_token(token) {
Some(token_lit) => {
match MetaItemLit::from_token_lit(token_lit, token.span) {
Some(lit) => {
match MetaItemLit::from_token_lit(lit, token.span) {
Ok(lit) => {
self.bump();
Some(lit)
}
Err(err) => {
let span = token.span;
let token::Literal(lit) = token.kind else {
unreachable!();
};
let span = token.uninterpolated_span();
self.bump();
report_lit_error(&self.sess, err, lit, span);
// Pack possible quotes and prefixes from the original literal into
Expand Down
21 changes: 19 additions & 2 deletions compiler/rustc_trait_selection/src/solve/canonicalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,25 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
t
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let r = self.infcx.shallow_resolve(r);
fn fold_region(&mut self, mut r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match self.canonicalize_mode {
CanonicalizeMode::Input => {
// Don't resolve infer vars in input, since it affects
// caching and may cause trait selection bugs which rely
// on regions to be equal.
}
CanonicalizeMode::Response { .. } => {
if let ty::ReVar(vid) = *r {
r = self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(self.infcx.tcx, vid);
}
}
}

let kind = match *r {
ty::ReLateBound(..) => return r,

Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
let new_canonical_response =
EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
if !new_canonical_response.value.var_values.is_identity() {
// We only check for modulo regions as we convert all regions in
// the input to new existentials, even if they're expected to be
// `'static` or a placeholder region.
if !new_canonical_response.value.var_values.is_identity_modulo_regions() {
bug!(
"unstable result: re-canonicalized goal={canonical_goal:#?} \
first_response={canonical_response:#?} \
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,12 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>(
Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate)
})
.chain(obligations)
.find(|o| !selcx.predicate_may_hold_fatal(o));
.find(|o| {
selcx.evaluate_root_obligation(o).map_or(
false, // Overflow has occurred, and treat the obligation as possibly holding.
|result| !result.may_apply(),
)
});

if let Some(failing_obligation) = opt_failing_obligation {
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
Expand Down
13 changes: 0 additions & 13 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,19 +518,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// The result is "true" if the obligation *may* hold and "false" if
// we can be sure it does not.

/// Evaluates whether the obligation `obligation` can be satisfied (by any means).
pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool {
debug!(?obligation, "predicate_may_hold_fatal");

// This fatal query is a stopgap that should only be used in standard mode,
// where we do not expect overflow to be propagated.
assert!(self.query_mode == TraitQueryMode::Standard);

self.evaluate_root_obligation(obligation)
.expect("Overflow should be caught earlier in standard query mode")
.may_apply()
}

/// Evaluates whether the obligation `obligation` can be satisfied
/// and returns an `EvaluationResult`. This is meant for the
/// *initial* call.
Expand Down
10 changes: 5 additions & 5 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
//! [`Rc`]: rc
//! [`RefCell`]: core::cell
// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
//
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(
Expand All @@ -75,11 +80,6 @@
))]
#![no_std]
#![needs_allocator]
// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
//
// Lints:
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(fuzzy_provenance_casts)]
Expand Down
13 changes: 7 additions & 6 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@
//! [array]: prim@array
//! [slice]: prim@slice
// To run std tests without x.py without ending up with two copies of std, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
//
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
#![doc(
Expand All @@ -202,12 +209,6 @@
no_global_oom_handling,
not(no_global_oom_handling)
))]
// To run std tests without x.py without ending up with two copies of std, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
// Don't link to std. We are std.
#![no_std]
// Tell the compiler to link to either panic_abort or panic_unwind
Expand Down
1 change: 1 addition & 0 deletions library/std/src/os/unix/net/ancillary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod libc {
pub use libc::c_int;
pub struct ucred;
pub struct cmsghdr;
pub struct sockcred2;
pub type pid_t = i32;
pub type gid_t = u32;
pub type uid_t = u32;
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/parser/lit-err-in-macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
macro_rules! f {
($abi:literal) => {
extern $abi fn f() {}
}
}

f!("Foo"__);
//~^ ERROR suffixes on string literals are invalid

fn main() {}
8 changes: 8 additions & 0 deletions tests/ui/parser/lit-err-in-macro.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: suffixes on string literals are invalid
--> $DIR/lit-err-in-macro.rs:7:4
|
LL | f!("Foo"__);
| ^^^^^^^ invalid suffix `__`

error: aborting due to previous error

9 changes: 9 additions & 0 deletions tests/ui/traits/issue-105231.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//~ ERROR overflow evaluating the requirement `A<A<A<A<A<A<A<...>>>>>>>: Send`
struct A<T>(B<T>);
//~^ ERROR recursive types `A` and `B` have infinite size
struct B<T>(A<A<T>>);
trait Foo {}
impl<T> Foo for T where T: Send {}
impl Foo for B<u8> {}

fn main() {}
Loading

0 comments on commit 2304917

Please sign in to comment.