Skip to content

Commit

Permalink
Auto merge of rust-lang#115960 - GuillaumeGomez:rollup-8tky3qu, r=Gui…
Browse files Browse the repository at this point in the history
…llaumeGomez

Rollup of 6 pull requests

Successful merges:

 - rust-lang#112725 (rustdoc-search: add support for type parameters)
 - rust-lang#114941 (Don't resolve generic impls that may be shadowed by dyn built-in impls)
 - rust-lang#115625 (Explain HRTB + infer limitations of old solver)
 - rust-lang#115839 (Bump libc to 0.2.148)
 - rust-lang#115924 (Don't complain on a single non-exhaustive 1-ZST)
 - rust-lang#115946 (panic when encountering an illegal cpumask in thread::available_parallelism)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Sep 19, 2023
2 parents ae9c330 + 57f1f91 commit 8769c26
Show file tree
Hide file tree
Showing 39 changed files with 1,605 additions and 488 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2142,9 +2142,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"

[[package]]
name = "libc"
version = "0.2.147"
version = "0.2.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
dependencies = [
"rustc-std-workspace-core",
]
Expand Down
48 changes: 29 additions & 19 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,25 +1201,35 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
);
return;
}
for (span, _trivial, non_exhaustive) in field_infos {
if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive {
tcx.struct_span_lint_hir(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
span,
"zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
|lint| {
let note = if non_exhaustive {
"is marked with `#[non_exhaustive]`"
} else {
"contains private fields"
};
let field_ty = tcx.def_path_str_with_args(def_id, args);
lint
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become non-zero-sized in the future."))
},
)
let mut prev_non_exhaustive_1zst = false;
for (span, _trivial, non_exhaustive_1zst) in field_infos {
if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst {
// If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
// Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
if non_trivial_count > 0 || prev_non_exhaustive_1zst {
tcx.struct_span_lint_hir(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
span,
"zero-sized fields in `repr(transparent)` cannot \
contain external non-exhaustive types",
|lint| {
let note = if non_exhaustive {
"is marked with `#[non_exhaustive]`"
} else {
"contains private fields"
};
let field_ty = tcx.def_path_str_with_args(def_id, args);
lint.note(format!(
"this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become \
non-zero-sized in the future."
))
},
)
} else {
prev_non_exhaustive_1zst = true;
}
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2945,6 +2945,33 @@ impl<'tcx> Ty<'tcx> {
_ => false,
}
}

pub fn is_known_rigid(self) -> bool {
match self.kind() {
Bool
| Char
| Int(_)
| Uint(_)
| Float(_)
| Adt(_, _)
| Foreign(_)
| Str
| Array(_, _)
| Slice(_)
| RawPtr(_)
| Ref(_, _, _)
| FnDef(_, _)
| FnPtr(_)
| Dynamic(_, _, _)
| Closure(_, _)
| Generator(_, _, _)
| GeneratorWitness(_)
| GeneratorWitnessMIR(_, _)
| Never
| Tuple(_) => true,
Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false,
}
}
}

/// Extra information about why we ended up with a particular variance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}

self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause);

// Return early if the trait is Debug or Display and the invocation
// originates within a standard library macro, because the output
// is otherwise overwhelming and unhelpful (see #85844 for an
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,14 @@ pub trait TypeErrCtxtExt<'tcx> {
candidate_impls: &[ImplCandidate<'tcx>],
span: Span,
);

fn explain_hrtb_projection(
&self,
diag: &mut Diagnostic,
pred: ty::PolyTraitPredicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cause: &ObligationCause<'tcx>,
);
}

fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) {
Expand Down Expand Up @@ -4027,6 +4035,71 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
}

fn explain_hrtb_projection(
&self,
diag: &mut Diagnostic,
pred: ty::PolyTraitPredicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cause: &ObligationCause<'tcx>,
) {
if pred.skip_binder().has_escaping_bound_vars() && pred.skip_binder().has_non_region_infer()
{
self.probe(|_| {
let ocx = ObligationCtxt::new(self);
let pred = self.instantiate_binder_with_placeholders(pred);
let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred);
ocx.register_obligation(Obligation::new(
self.tcx,
ObligationCause::dummy(),
param_env,
pred,
));
if !ocx.select_where_possible().is_empty() {
// encountered errors.
return;
}

if let ObligationCauseCode::FunctionArgumentObligation {
call_hir_id,
arg_hir_id,
parent_code: _,
} = cause.code()
{
let arg_span = self.tcx.hir().span(*arg_hir_id);
let mut sp: MultiSpan = arg_span.into();

sp.push_span_label(
arg_span,
"the trait solver is unable to infer the \
generic types that should be inferred from this argument",
);
sp.push_span_label(
self.tcx.hir().span(*call_hir_id),
"add turbofish arguments to this call to \
specify the types manually, even if it's redundant",
);
diag.span_note(
sp,
"this is a known limitation of the trait solver that \
will be lifted in the future",
);
} else {
let mut sp: MultiSpan = cause.span.into();
sp.push_span_label(
cause.span,
"try adding turbofish arguments to this expression to \
specify the types manually, even if it's redundant",
);
diag.span_note(
sp,
"this is a known limitation of the trait solver that \
will be lifted in the future",
);
}
});
}
}
}

/// Add a hint to add a missing borrow or remove an unnecessary one.
Expand Down
25 changes: 24 additions & 1 deletion compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,34 @@ fn resolve_associated_item<'tcx>(
false
}
};

if !eligible {
return Ok(None);
}

// HACK: We may have overlapping `dyn Trait` built-in impls and
// user-provided blanket impls. Detect that case here, and return
// ambiguity.
//
// This should not affect totally monomorphized contexts, only
// resolve calls that happen polymorphically, such as the mir-inliner
// and const-prop (and also some lints).
let self_ty = rcvr_args.type_at(0);
if !self_ty.is_known_rigid() {
let predicates = tcx
.predicates_of(impl_data.impl_def_id)
.instantiate(tcx, impl_data.args)
.predicates;
let sized_def_id = tcx.lang_items().sized_trait();
// If we find a `Self: Sized` bound on the item, then we know
// that `dyn Trait` can certainly never apply here.
if !predicates.into_iter().filter_map(ty::Clause::as_trait_clause).any(|clause| {
Some(clause.def_id()) == sized_def_id
&& clause.skip_binder().self_ty() == self_ty
}) {
return Ok(None);
}
}

// Any final impl is required to define all associated items.
if !leaf_def.item.defaultness(tcx).has_value() {
let guard = tcx.sess.delay_span_bug(
Expand Down
2 changes: 1 addition & 1 deletion library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true }
libc = { version = "0.2.148", default-features = false, features = ['rustc-dep-of-std'], public = true }
compiler_builtins = { version = "0.1.100" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
Expand Down
6 changes: 4 additions & 2 deletions library/std/src/sys/unix/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,10 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
if libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) == 0 {
let count = libc::CPU_COUNT(&set) as usize;
let count = count.min(quota);
// SAFETY: affinity mask can't be empty and the quota gets clamped to a minimum of 1
return Ok(NonZeroUsize::new_unchecked(count));
// reported to occur on MIPS kernels older than our minimum supported kernel version for those targets
let count = NonZeroUsize::new(count)
.expect("CPU count must be > 0. This may be a bug in sched_getaffinity(); try upgrading the kernel.");
return Ok(count);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustdoc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- [Command-line arguments](command-line-arguments.md)
- [How to read rustdoc output](how-to-read-rustdoc.md)
- [In-doc settings](read-documentation/in-doc-settings.md)
- [Search](read-documentation/search.md)
- [How to write documentation](how-to-write-documentation.md)
- [What to include (and exclude)](write-documentation/what-to-include.md)
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
Expand Down
55 changes: 5 additions & 50 deletions src/doc/rustdoc/src/how-to-read-rustdoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,56 +75,11 @@ or the current item whose documentation is being displayed.
## The Theme Picker and Search Interface

When viewing `rustdoc`'s output in a browser with JavaScript enabled,
a dynamic interface appears at the top of the page composed of the search
interface, help screen, and options.

### The Search Interface

Typing in the search bar instantly searches the available documentation for
the string entered with a fuzzy matching algorithm that is tolerant of minor
typos.

By default, the search results given are "In Names",
meaning that the fuzzy match is made against the names of items.
Matching names are shown on the left, and the first few words of their
descriptions are given on the right.
By clicking an item, you will navigate to its particular documentation.

There are two other sets of results, shown as tabs in the search results pane.
"In Parameters" shows matches for the string in the types of parameters to
functions, and "In Return Types" shows matches in the return types of functions.
Both are very useful when looking for a function whose name you can't quite
bring to mind when you know the type you have or want.

Names in the search interface can be prefixed with an item type followed by a
colon (such as `mod:`) to restrict the results to just that kind of item. Also,
searching for `println!` will search for a macro named `println`, just like
searching for `macro:println` does.

Function signature searches can query generics, wrapped in angle brackets, and
traits are normalized like types in the search engine. For example, a function
with the signature `fn my_function<I: Iterator<Item=u32>>(input: I) -> usize`
can be matched with the following queries:

* `Iterator<u32> -> usize`
* `trait:Iterator<primitive:u32> -> primitive:usize`
* `Iterator -> usize`

Generics and function parameters are order-agnostic, but sensitive to nesting
and number of matches. For example, a function with the signature
`fn read_all(&mut self: impl Read) -> Result<Vec<u8>, Error>`
will match these queries:

* `Read -> Result<Vec<u8>, Error>`
* `Read -> Result<Error, Vec>`
* `Read -> Result<Vec<u8>>`

But it *does not* match `Result<Vec, u8>` or `Result<u8<Vec>>`.

Function signature searches also support arrays and slices. The explicit name
`primitive:slice<u8>` and `primitive:array<u8>` can be used to match a slice
or array of bytes, while square brackets `[u8]` will match either one. Empty
square brackets, `[]`, will match any slice regardless of what it contains.
a dynamic interface appears at the top of the page composed of the [search]
interface, help screen, and [options].

[options]: read-documentation/in-doc-settings.html
[search]: read-documentation/search.md

Paths are supported as well, you can look for `Vec::new` or `Option::Some` or
even `module::module_child::another_child::struct::field`. Whitespace characters
Expand Down
Loading

0 comments on commit 8769c26

Please sign in to comment.