Skip to content

Commit

Permalink
Auto merge of #98521 - JohnTitor:rollup-tl9sblx, r=JohnTitor
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #98371 (Fix printing `impl trait` under binders)
 - #98385 (Work around llvm 12's memory ordering restrictions.)
 - #98474 (x.py: Support systems with only `python3` not `python`)
 - #98488 (Bump RLS to latest master on rust-lang/rls)
 - #98491 (Fix backtrace UI test when panic=abort is used)
 - #98502 (Fix source sidebar hover in ayu theme)
 - #98509 (diagnostics: consider parameter count when suggesting smart pointers)
 - #98513 (Fix LLVM rebuild with download-ci-llvm.)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 26, 2022
2 parents 639a655 + fba8dfd commit 0e1a6fb
Show file tree
Hide file tree
Showing 17 changed files with 355 additions and 129 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3054,7 +3054,6 @@ name = "racer"
version = "2.2.2"
dependencies = [
"bitflags",
"clap 2.34.0",
"derive_more",
"env_logger 0.7.1",
"humantime 2.0.1",
Expand Down Expand Up @@ -3278,7 +3277,7 @@ dependencies = [
"difference",
"env_logger 0.9.0",
"futures 0.3.19",
"heck 0.3.1",
"heck 0.4.0",
"home",
"itertools",
"jsonrpc-core",
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1064,11 +1064,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
dst: &'ll Value,
cmp: &'ll Value,
src: &'ll Value,
order: rustc_codegen_ssa::common::AtomicOrdering,
mut order: rustc_codegen_ssa::common::AtomicOrdering,
failure_order: rustc_codegen_ssa::common::AtomicOrdering,
weak: bool,
) -> &'ll Value {
let weak = if weak { llvm::True } else { llvm::False };
if llvm_util::get_version() < (13, 0, 0) {
use rustc_codegen_ssa::common::AtomicOrdering::*;
// Older llvm has the pre-C++17 restriction on
// success and failure memory ordering,
// requiring the former to be at least as strong as the latter.
// So, for llvm 12, we upgrade the success ordering to a stronger
// one if necessary.
match (order, failure_order) {
(Relaxed, Acquire) => order = Acquire,
(Release, Acquire) => order = AcquireRelease,
(_, SequentiallyConsistent) => order = SequentiallyConsistent,
_ => {}
}
}
unsafe {
llvm::LLVMRustBuildAtomicCmpXchg(
self.llbuilder,
Expand Down
233 changes: 120 additions & 113 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ pub trait PrettyPrinter<'tcx>:
value.as_ref().skip_binder().print(self)
}

fn wrap_binder<T, F: Fn(&T, Self) -> Result<Self, fmt::Error>>(
fn wrap_binder<T, F: FnOnce(&T, Self) -> Result<Self, fmt::Error>>(
self,
value: &ty::Binder<'tcx, T>,
f: F,
Expand Down Expand Up @@ -773,26 +773,26 @@ pub trait PrettyPrinter<'tcx>:
def_id: DefId,
substs: &'tcx ty::List<ty::GenericArg<'tcx>>,
) -> Result<Self::Type, Self::Error> {
define_scoped_cx!(self);
let tcx = self.tcx();

// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
let bounds = self.tcx().bound_explicit_item_bounds(def_id);
let bounds = tcx.bound_explicit_item_bounds(def_id);

let mut traits = FxIndexMap::default();
let mut fn_traits = FxIndexMap::default();
let mut is_sized = false;

for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
let predicate = predicate.subst(self.tcx(), substs);
let predicate = predicate.subst(tcx, substs);
let bound_predicate = predicate.kind();

match bound_predicate.skip_binder() {
ty::PredicateKind::Trait(pred) => {
let trait_ref = bound_predicate.rebind(pred.trait_ref);

// Don't print + Sized, but rather + ?Sized if absent.
if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
is_sized = true;
continue;
}
Expand All @@ -801,7 +801,7 @@ pub trait PrettyPrinter<'tcx>:
}
ty::PredicateKind::Projection(pred) => {
let proj_ref = bound_predicate.rebind(pred);
let trait_ref = proj_ref.required_poly_trait_ref(self.tcx());
let trait_ref = proj_ref.required_poly_trait_ref(tcx);

// Projection type entry -- the def-id for naming, and the ty.
let proj_ty = (proj_ref.projection_def_id(), proj_ref.term());
Expand All @@ -817,148 +817,155 @@ pub trait PrettyPrinter<'tcx>:
}
}

write!(self, "impl ")?;

let mut first = true;
// Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait
let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized;

p!("impl");

for (fn_once_trait_ref, entry) in fn_traits {
// Get the (single) generic ty (the args) of this FnOnce trait ref.
let generics = self.tcx().generics_of(fn_once_trait_ref.def_id());
let args =
generics.own_substs_no_defaults(self.tcx(), fn_once_trait_ref.skip_binder().substs);

match (entry.return_ty, args[0].expect_ty()) {
// We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
// a return type.
(Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
let name = if entry.fn_trait_ref.is_some() {
"Fn"
} else if entry.fn_mut_trait_ref.is_some() {
"FnMut"
} else {
"FnOnce"
};
write!(self, "{}", if first { "" } else { " + " })?;
write!(self, "{}", if paren_needed { "(" } else { "" })?;

p!(
write("{}", if first { " " } else { " + " }),
write("{}{}(", if paren_needed { "(" } else { "" }, name)
);
self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut cx| {
define_scoped_cx!(cx);
// Get the (single) generic ty (the args) of this FnOnce trait ref.
let generics = tcx.generics_of(trait_ref.def_id);
let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);

match (entry.return_ty, args[0].expect_ty()) {
// We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded
// a return type.
(Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => {
let name = if entry.fn_trait_ref.is_some() {
"Fn"
} else if entry.fn_mut_trait_ref.is_some() {
"FnMut"
} else {
"FnOnce"
};

for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
if idx > 0 {
p!(", ");
p!(write("{}(", name));

for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() {
if idx > 0 {
p!(", ");
}
p!(print(ty));
}
p!(print(ty));
}

p!(")");
if let Term::Ty(ty) = return_ty.skip_binder() {
if !ty.is_unit() {
p!(" -> ", print(return_ty));
p!(")");
if let Term::Ty(ty) = return_ty.skip_binder() {
if !ty.is_unit() {
p!(" -> ", print(return_ty));
}
}
}
p!(write("{}", if paren_needed { ")" } else { "" }));
p!(write("{}", if paren_needed { ")" } else { "" }));

first = false;
}
// If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
// trait_refs we collected in the OpaqueFnEntry as normal trait refs.
_ => {
if entry.has_fn_once {
traits.entry(fn_once_trait_ref).or_default().extend(
// Group the return ty with its def id, if we had one.
entry
.return_ty
.map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)),
);
}
if let Some(trait_ref) = entry.fn_mut_trait_ref {
traits.entry(trait_ref).or_default();
first = false;
}
if let Some(trait_ref) = entry.fn_trait_ref {
traits.entry(trait_ref).or_default();
// If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the
// trait_refs we collected in the OpaqueFnEntry as normal trait refs.
_ => {
if entry.has_fn_once {
traits.entry(fn_once_trait_ref).or_default().extend(
// Group the return ty with its def id, if we had one.
entry
.return_ty
.map(|ty| (tcx.lang_items().fn_once_output().unwrap(), ty)),
);
}
if let Some(trait_ref) = entry.fn_mut_trait_ref {
traits.entry(trait_ref).or_default();
}
if let Some(trait_ref) = entry.fn_trait_ref {
traits.entry(trait_ref).or_default();
}
}
}
}

Ok(cx)
})?;
}

// Print the rest of the trait types (that aren't Fn* family of traits)
for (trait_ref, assoc_items) in traits {
p!(
write("{}", if first { " " } else { " + " }),
print(trait_ref.skip_binder().print_only_trait_name())
);
write!(self, "{}", if first { "" } else { " + " })?;

self = self.wrap_binder(&trait_ref, |trait_ref, mut cx| {
define_scoped_cx!(cx);
p!(print(trait_ref.print_only_trait_name()));

let generics = self.tcx().generics_of(trait_ref.def_id());
let args = generics.own_substs_no_defaults(self.tcx(), trait_ref.skip_binder().substs);
let generics = tcx.generics_of(trait_ref.def_id);
let args = generics.own_substs_no_defaults(tcx, trait_ref.substs);

if !args.is_empty() || !assoc_items.is_empty() {
let mut first = true;
if !args.is_empty() || !assoc_items.is_empty() {
let mut first = true;

for ty in args {
if first {
p!("<");
first = false;
} else {
p!(", ");
for ty in args {
if first {
p!("<");
first = false;
} else {
p!(", ");
}
p!(print(ty));
}
p!(print(trait_ref.rebind(*ty)));
}

for (assoc_item_def_id, term) in assoc_items {
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
// unless we can find out what generator return type it comes from.
let term = if let Some(ty) = term.skip_binder().ty()
&& let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind()
&& Some(*item_def_id) == self.tcx().lang_items().generator_return()
{
if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
let return_ty = substs.as_generator().return_ty();
if !return_ty.is_ty_infer() {
return_ty.into()
for (assoc_item_def_id, term) in assoc_items {
// Skip printing `<[generator@] as Generator<_>>::Return` from async blocks,
// unless we can find out what generator return type it comes from.
let term = if let Some(ty) = term.skip_binder().ty()
&& let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind()
&& Some(*item_def_id) == tcx.lang_items().generator_return()
{
if let ty::Generator(_, substs, _) = substs.type_at(0).kind() {
let return_ty = substs.as_generator().return_ty();
if !return_ty.is_ty_infer() {
return_ty.into()
} else {
continue;
}
} else {
continue;
}
} else {
continue;
}
} else {
term.skip_binder()
};
term.skip_binder()
};

if first {
p!("<");
first = false;
} else {
p!(", ");
}
if first {
p!("<");
first = false;
} else {
p!(", ");
}

p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name));
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name));

match term {
Term::Ty(ty) => {
p!(print(ty))
}
Term::Const(c) => {
p!(print(c));
}
};
}
match term {
Term::Ty(ty) => {
p!(print(ty))
}
Term::Const(c) => {
p!(print(c));
}
};
}

if !first {
p!(">");
if !first {
p!(">");
}
}
}

first = false;
first = false;
Ok(cx)
})?;
}

if !is_sized {
p!(write("{}?Sized", if first { " " } else { " + " }));
write!(self, "{}?Sized", if first { "" } else { " + " })?;
} else if first {
p!(" Sized");
write!(self, "Sized")?;
}

Ok(self)
Expand Down Expand Up @@ -1869,7 +1876,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
self.pretty_in_binder(value)
}

fn wrap_binder<T, C: Fn(&T, Self) -> Result<Self, Self::Error>>(
fn wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, Self::Error>>(
self,
value: &ty::Binder<'tcx, T>,
f: C,
Expand Down Expand Up @@ -2256,7 +2263,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
Ok(inner)
}

pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
pub fn pretty_wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, fmt::Error>>(
self,
value: &ty::Binder<'tcx, T>,
f: C,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span,
rcvr_ty,
item_name,
args.map(|args| args.len()),
source,
out_of_scope_traits,
&unsatisfied_predicates,
Expand Down Expand Up @@ -1732,6 +1733,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
rcvr_ty: Ty<'tcx>,
item_name: Ident,
inputs_len: Option<usize>,
source: SelfSource<'tcx>,
valid_out_of_scope_traits: Vec<DefId>,
unsatisfied_predicates: &[(
Expand Down Expand Up @@ -1808,7 +1810,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
// implement the `AsRef` trait.
let skip = skippable.contains(&did)
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name));
|| (("Pin::new" == *pre) && (sym::as_ref == item_name.name))
|| inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().inputs().len() != inputs_len);
// Make sure the method is defined for the *actual* receiver: we don't
// want to treat `Box<Self>` as a receiver if it only works because of
// an autoderef to `&self`
Expand Down
Loading

0 comments on commit 0e1a6fb

Please sign in to comment.