Skip to content

Rollup of 9 pull requests #103419

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 21 commits into from
Closed
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
419fde7
Handle RPITITs properly in register_hidden_type
compiler-errors Oct 21, 2022
9f6b9dd
Delay ambiguity span bug in normalize query iff not rustdoc
compiler-errors Oct 21, 2022
cb61113
tests
compiler-errors Oct 21, 2022
7280f3d
Truncate thread names on Linux and Apple targets
cuviper Oct 22, 2022
12e4584
Move truncation next to other thread tests for tidy
cuviper Oct 22, 2022
ed40d46
Properly escape quotes when suggesting switching between char/string …
clubby789 Oct 22, 2022
8762485
Update UI tests
clubby789 Oct 22, 2022
2ac29f6
rustdoc: remove unused CSS class `.result-description`
notriddle Oct 22, 2022
aa8931c
Introduce subst_iter and subst_iter_copied on EarlyBinder
compiler-errors Oct 16, 2022
62b65b5
Change `unknown_lint` applicability to `MaybeIncorrect`
smoelius Oct 22, 2022
94a9ee3
Use functions for headings rustodoc GUI test
GuillaumeGomez Oct 22, 2022
9f0503e
Fix typo in docs of `String::leak`.
finnbear Oct 22, 2022
77f421c
Rollup merge of #103123 - compiler-errors:early-binder-iter, r=cjgillot
notriddle Oct 22, 2022
6cdbc6b
Rollup merge of #103354 - clubby789:escape-string-literals, r=compile…
notriddle Oct 22, 2022
9f75e99
Rollup merge of #103355 - compiler-errors:rpitit-default-check, r=oli…
notriddle Oct 22, 2022
0ab4934
Rollup merge of #103368 - compiler-errors:normalization-ambiguity-bug…
notriddle Oct 22, 2022
dcfb161
Rollup merge of #103379 - cuviper:truncate-thread-name, r=thomcc
notriddle Oct 22, 2022
0a7a334
Rollup merge of #103388 - notriddle:notriddle/result-description, r=G…
notriddle Oct 22, 2022
c2442c3
Rollup merge of #103399 - smoelius:unknown-lint-maybe-incorrect, r=fe…
notriddle Oct 22, 2022
e84fe91
Rollup merge of #103401 - GuillaumeGomez:gui-test-headings-cleanup, r…
notriddle Oct 22, 2022
cbfc235
Rollup merge of #103412 - finnbear:fix_docs_typo_string_leak, r=thomcc
notriddle Oct 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions compiler/rustc_hir_analysis/src/check/compare_method.rs
Original file line number Diff line number Diff line change
@@ -664,10 +664,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
});
self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
// Recurse into bounds
for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
let pred_span = pred.0.1;

let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
ObligationCause::misc(self.span, self.body_id),
@@ -1752,15 +1749,10 @@ pub fn check_type_bounds<'tcx>(

let obligations = tcx
.bound_explicit_item_bounds(trait_ty.def_id)
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.map(|(bound, span)| {
debug!(?bound);
// this is where opaque type is found
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
.subst_iter_copied(tcx, rebased_substs)
.map(|(concrete_ty_bound, span)| {
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);

traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
})
.collect();
debug!("check_type_bounds: item_bounds={:?}", obligations);
7 changes: 5 additions & 2 deletions compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
@@ -514,8 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

for ty in [first_ty, second_ty] {
for pred in self.tcx.bound_explicit_item_bounds(rpit_def_id).transpose_iter() {
let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx, substs);
for (pred, _) in self
.tcx
.bound_explicit_item_bounds(rpit_def_id)
.subst_iter_copied(self.tcx, substs)
{
let pred = match pred.kind().skip_binder() {
ty::PredicateKind::Trait(mut trait_pred) => {
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
31 changes: 14 additions & 17 deletions compiler/rustc_hir_typeck/src/closure.rs
Original file line number Diff line number Diff line change
@@ -176,24 +176,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *expected_ty.kind() {
ty::Opaque(def_id, substs) => {
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
let sig = bounds
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(pred, span)| match pred.0.kind().skip_binder() {
let sig =
bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
.kind()
.skip_binder()
{
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
Some(span.0),
pred.0
.kind()
.rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
Some(span),
pred.kind().rebind(proj_predicate),
),
_ => None,
});

let kind = bounds
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.filter_map(|(pred, _)| match pred.0.kind().skip_binder() {
.0
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(tp) => {
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
}
@@ -697,18 +696,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Opaque(def_id, substs) => self
.tcx
.bound_explicit_item_bounds(def_id)
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
.subst_iter_copied(self.tcx, substs)
.find_map(|(p, s)| get_future_output(p, s))?,
ty::Error(_) => return None,
ty::Projection(proj)
if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
{
self.tcx
.bound_explicit_item_bounds(proj.item_def_id)
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))?
.subst_iter_copied(self.tcx, proj.substs)
.find_map(|(p, s)| get_future_output(p, s))?
}
_ => span_bug!(
self.tcx.def_span(expr_def_id),
26 changes: 22 additions & 4 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
@@ -338,8 +338,7 @@ impl<'tcx> InferCtxt<'tcx> {

let bounds = self.tcx.bound_explicit_item_bounds(*def_id);

for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
let predicate = predicate.subst(self.tcx, substs);
for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) {
let output = predicate
.kind()
.map_bound(|kind| match kind {
@@ -2272,6 +2271,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
}
FailureCode::Error0308(failure_str) => {
fn escape_literal(s: &str) -> String {
let mut escaped = String::with_capacity(s.len());
let mut chrs = s.chars().peekable();
while let Some(first) = chrs.next() {
match (first, chrs.peek()) {
('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
escaped.push('\\');
escaped.push(delim);
chrs.next();
}
('"' | '\'', _) => {
escaped.push('\\');
escaped.push(first)
}
(c, _) => escaped.push(c),
};
}
escaped
}
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
if let Some((expected, found)) = trace.values.ty() {
match (expected.kind(), found.kind()) {
@@ -2293,7 +2311,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
format!("'{}'", code),
format!("'{}'", escape_literal(code)),
Applicability::MachineApplicable,
);
}
@@ -2308,7 +2326,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err.span_suggestion(
span,
"if you meant to write a `str` literal, use double quotes",
format!("\"{}\"", code),
format!("\"{}\"", escape_literal(code)),
Applicability::MachineApplicable,
);
}
19 changes: 14 additions & 5 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
use crate::traits;
use hir::def::DefKind;
use hir::def_id::{DefId, LocalDefId};
use hir::{HirId, OpaqueTyOrigin};
use rustc_data_structures::sync::Lrc;
@@ -543,16 +544,18 @@ impl<'tcx> InferCtxt<'tcx> {

let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());

for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
debug!(?predicate);
let predicate = predicate.subst(tcx, substs);

for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
let predicate = predicate.fold_with(&mut BottomUpFolder {
tcx,
ty_op: |ty| match *ty.kind() {
// We can't normalize associated types from `rustc_infer`,
// but we can eagerly register inference variables for them.
ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
// FIXME(RPITIT): Don't replace RPITITs with inference vars.
ty::Projection(projection_ty)
if !projection_ty.has_escaping_bound_vars()
&& tcx.def_kind(projection_ty.item_def_id)
!= DefKind::ImplTraitPlaceholder =>
{
self.infer_projection(
param_env,
projection_ty,
@@ -568,6 +571,12 @@ impl<'tcx> InferCtxt<'tcx> {
{
hidden_ty
}
// FIXME(RPITIT): This can go away when we move to associated types
ty::Projection(proj)
if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
{
hidden_ty
}
_ => ty,
},
lt_op: |lt| lt,
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/levels.rs
Original file line number Diff line number Diff line change
@@ -960,7 +960,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
sp,
"did you mean",
suggestion,
Applicability::MachineApplicable,
Applicability::MaybeIncorrect,
);
}
lint
12 changes: 5 additions & 7 deletions compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
Original file line number Diff line number Diff line change
@@ -91,14 +91,12 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
// For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
// e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
// with `impl Send: OtherTrait`.
for assoc_pred_and_span in
cx.tcx.bound_explicit_item_bounds(proj.projection_ty.item_def_id).transpose_iter()
for (assoc_pred, assoc_pred_span) in cx
.tcx
.bound_explicit_item_bounds(proj.projection_ty.item_def_id)
.subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
{
let assoc_pred_span = assoc_pred_and_span.0.1;
let assoc_pred = assoc_pred_and_span
.map_bound(|(pred, _)| *pred)
.subst(cx.tcx, &proj.projection_ty.substs)
.fold_with(proj_replacer);
let assoc_pred = assoc_pred.fold_with(proj_replacer);
let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
continue;
};
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
@@ -795,8 +795,7 @@ pub trait PrettyPrinter<'tcx>:
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(tcx, substs);
for (predicate, _) in bounds.subst_iter_copied(tcx, substs) {
let bound_predicate = predicate.kind();

match bound_predicate.skip_binder() {
23 changes: 23 additions & 0 deletions compiler/rustc_middle/src/ty/subst.rs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};

use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::{Interned, WithStableHash};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
@@ -558,6 +559,28 @@ impl<T, U> EarlyBinder<(T, U)> {
}
}

impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
pub fn subst_iter(
self,
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
}
}

impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
EarlyBinder<T>
{
pub fn subst_iter_copied(
self,
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
}
}

pub struct EarlyBinderIter<T> {
t: T,
}
19 changes: 17 additions & 2 deletions compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
Original file line number Diff line number Diff line change
@@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error(
} else {
("", "if you meant to write a `str` literal, use double quotes")
};

let mut escaped = String::with_capacity(lit.len());
let mut chrs = lit.chars().peekable();
while let Some(first) = chrs.next() {
match (first, chrs.peek()) {
('\\', Some('"')) => {
escaped.push('\\');
escaped.push('"');
chrs.next();
}
('"', _) => {
escaped.push('\\');
escaped.push('"')
}
(c, _) => escaped.push(c),
};
}
handler.span_suggestion(
span_with_quotes,
msg,
format!("{}\"{}\"", prefix, lit),
format!("{prefix}\"{escaped}\""),
Applicability::MachineApplicable,
);
}
21 changes: 19 additions & 2 deletions compiler/rustc_trait_selection/src/traits/query/normalize.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;

use std::ops::ControlFlow;

@@ -253,7 +254,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
self.infcx.instantiate_query_response_and_region_obligations(
@@ -296,7 +305,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
// Rustdoc normalizes possibly not well-formed types, so only
// treat this as a bug if we're not in rustdoc.
if !tcx.sess.opts.actually_rustdoc {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
);
}
return Err(NoSolution);
}
let InferOk { value: result, obligations } =
self.infcx.instantiate_query_response_and_region_obligations(
2 changes: 1 addition & 1 deletion library/alloc/src/string.rs
Original file line number Diff line number Diff line change
@@ -1851,7 +1851,7 @@ impl String {
}

/// Consumes and leaks the `String`, returning a mutable reference to the contents,
/// `&'a mut str`.
/// `&'static mut str`.
///
/// This is mainly useful for data that lives for the remainder of
/// the program's life. Dropping the returned reference will cause a memory
18 changes: 18 additions & 0 deletions library/std/src/sys/unix/thread.rs
Original file line number Diff line number Diff line change
@@ -132,8 +132,11 @@ impl Thread {

#[cfg(target_os = "linux")]
pub fn set_name(name: &CStr) {
const TASK_COMM_LEN: usize = 16;

unsafe {
// Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
let name = truncate_cstr(name, TASK_COMM_LEN);
libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
}
}
@@ -148,6 +151,7 @@ impl Thread {
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
pub fn set_name(name: &CStr) {
unsafe {
let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
libc::pthread_setname_np(name.as_ptr());
}
}
@@ -276,6 +280,20 @@ impl Drop for Thread {
}
}

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
fn truncate_cstr(cstr: &CStr, max_with_nul: usize) -> crate::borrow::Cow<'_, CStr> {
use crate::{borrow::Cow, ffi::CString};

if cstr.to_bytes_with_nul().len() > max_with_nul {
let bytes = cstr.to_bytes()[..max_with_nul - 1].to_vec();
// SAFETY: the non-nul bytes came straight from a CStr.
// (CString will add the terminating nul.)
Cow::Owned(unsafe { CString::from_vec_unchecked(bytes) })
} else {
Cow::Borrowed(cstr)
}
}

pub fn available_parallelism() -> io::Result<NonZeroUsize> {
cfg_if::cfg_if! {
if #[cfg(any(
25 changes: 25 additions & 0 deletions library/std/src/thread/tests.rs
Original file line number Diff line number Diff line change
@@ -37,6 +37,31 @@ fn test_named_thread() {
.unwrap();
}

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[test]
fn test_named_thread_truncation() {
use crate::ffi::CStr;

let long_name = crate::iter::once("test_named_thread_truncation")
.chain(crate::iter::repeat(" yada").take(100))
.collect::<String>();

let result = Builder::new().name(long_name.clone()).spawn(move || {
// Rust remembers the full thread name itself.
assert_eq!(thread::current().name(), Some(long_name.as_str()));

// But the system is limited -- make sure we successfully set a truncation.
let mut buf = vec![0u8; long_name.len() + 1];
unsafe {
libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len());
}
let cstr = CStr::from_bytes_until_nul(&buf).unwrap();
assert!(cstr.to_bytes().len() > 0);
assert!(long_name.as_bytes().starts_with(cstr.to_bytes()));
});
result.unwrap().join().unwrap();
}

#[test]
#[should_panic]
fn test_invalid_named_thread() {
6 changes: 3 additions & 3 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
@@ -920,7 +920,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
flex-flow: row wrap;
}

.search-results .result-name, .search-results div.desc, .search-results .result-description {
.search-results .result-name, .search-results div.desc {
width: 50%;
}
.search-results .result-name {
@@ -1899,10 +1899,10 @@ in storage.js
border-bottom: 1px solid #aaa9;
padding: 5px 0px;
}
.search-results .result-name, .search-results div.desc, .search-results .result-description {
.search-results .result-name, .search-results div.desc {
width: 100%;
}
.search-results div.desc, .search-results .result-description, .item-right {
.search-results div.desc, .item-right {
padding-left: 2em;
}

176 changes: 76 additions & 100 deletions src/test/rustdoc-gui/headings.goml
Original file line number Diff line number Diff line change
@@ -150,109 +150,85 @@ assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "20px"})
assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})

// Checking colors now.
// Needed to check colors
show-text: true
local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
assert-css: (
".top-doc .docblock h2",
{"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
)
assert-css: (
".top-doc .docblock h3",
{"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
)
assert-css: (
".top-doc .docblock h4",
{"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
)
assert-css: (
".top-doc .docblock h5",
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h4",
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h5",
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h6",
{"color": "rgb(0, 0, 0)", "border-bottom-width": "0px"},
)

local-storage: {"rustdoc-theme": "dark"}
reload:
assert-css: (
".top-doc .docblock h2",
{"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
)
assert-css: (
".top-doc .docblock h3",
{"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
)
assert-css: (
".top-doc .docblock h4",
{"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
)
assert-css: (
".top-doc .docblock h5",
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h4",
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h5",
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h6",
{"color": "rgb(221, 221, 221)", "border-bottom-width": "0px"},
define-function: (
"check-colors",
(theme, heading_color, small_heading_color, heading_border_color),
[
("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
("reload"),
("assert-css", (
".top-doc .docblock h2",
{"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
)),
("assert-css", (
".top-doc .docblock h3",
{"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
)),
("assert-css", (
".top-doc .docblock h4",
{"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
)),
("assert-css", (
".top-doc .docblock h5",
{"color": |small_heading_color|, "border-bottom-width": "0px"},
)),
("assert-css", (
"#implementations-list .docblock h4",
{"color": |heading_color|, "border-bottom-width": "0px"},
)),
("assert-css", (
"#implementations-list .docblock h5",
{"color": |small_heading_color|, "border-bottom-width": "0px"},
)),
("assert-css", (
"#implementations-list .docblock h6",
{"color": |small_heading_color|, "border-bottom-width": "0px"},
)),
],
)
call-function: (
"check-colors",
{
"theme": "ayu",
"heading_color": "rgb(255, 255, 255)",
"small_heading_color": "rgb(197, 197, 197)",
"heading_border_color": "rgb(92, 103, 115)",
},
)
call-function: (
"check-colors",
{
"theme": "dark",
"heading_color": "rgb(221, 221, 221)",
"small_heading_color": "rgb(221, 221, 221)",
"heading_border_color": "rgb(210, 210, 210)",
},
)
call-function: (
"check-colors",
{
"theme": "light",
"heading_color": "rgb(0, 0, 0)",
"small_heading_color": "rgb(0, 0, 0)",
"heading_border_color": "rgb(221, 221, 221)",
},
)

define-function: (
"check-since-color",
(theme),
[
("local-storage", {"rustdoc-theme": |theme|}),
("reload"),
("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)),
],
)

local-storage: {"rustdoc-theme": "ayu"}
reload:
assert-css: (
".top-doc .docblock h2",
{"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
)
assert-css: (
".top-doc .docblock h2",
{"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
)
assert-css: (
".top-doc .docblock h4",
{"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
)
assert-css: (
".top-doc .docblock h5",
{"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h4",
{"color": "rgb(255, 255, 255)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h5",
{"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
)
assert-css: (
"#implementations-list .docblock h6",
{"color": "rgb(197, 197, 197)", "border-bottom-width": "0px"},
)

local-storage: {"rustdoc-theme": "light"}
goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)

local-storage: {"rustdoc-theme": "dark"}
reload:
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)

local-storage: {"rustdoc-theme": "ayu"}
reload:
assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
call-function: ("check-since-color", ("ayu"))
call-function: ("check-since-color", ("dark"))
call-function: ("check-since-color", ("light"))
24 changes: 24 additions & 0 deletions src/test/rustdoc/not-wf-ambiguous-normalization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// compile-flags: -Znormalize-docs

#![feature(type_alias_impl_trait)]

trait Allocator {
type Buffer;
}

struct DefaultAllocator;

// This unconstrained impl parameter causes the normalization of
// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
// which caused an ICE with `-Znormalize-docs`.
impl<T> Allocator for DefaultAllocator {
type Buffer = ();
}

type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);

fn foo() -> A {
|_| ()
}

fn main() {}
13 changes: 13 additions & 0 deletions src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// edition:2021

#![allow(incomplete_features)]
#![feature(async_fn_in_trait)]

pub trait Foo {
async fn woopsie_async(&self) -> String {
42
//~^ ERROR mismatched types
}
}

fn main() {}
11 changes: 11 additions & 0 deletions src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0308]: mismatched types
--> $DIR/default-body-type-err-2.rs:8:9
|
LL | 42
| ^^- help: try using a conversion method: `.to_string()`
| |
| expected struct `String`, found integer

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
13 changes: 13 additions & 0 deletions src/test/ui/impl-trait/in-trait/default-body-type-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![allow(incomplete_features)]
#![feature(return_position_impl_trait_in_trait)]

use std::ops::Deref;

pub trait Foo {
fn lol(&self) -> impl Deref<Target = String> {
//~^ type mismatch resolving `<&i32 as Deref>::Target == String`
&1i32
}
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
--> $DIR/default-body-type-err.rs:7:22
|
LL | fn lol(&self) -> impl Deref<Target = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String`
LL |
LL | &1i32
| ----- return type was inferred to be `&i32` here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0271`.
2 changes: 1 addition & 1 deletion src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// known-bug: #102688
// check-pass
// edition:2021

#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
12 changes: 0 additions & 12 deletions src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr

This file was deleted.

85 changes: 85 additions & 0 deletions src/test/ui/impl-trait/issue-103181-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// edition:2021

mod hyper {
use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task::Poll};

pub trait HttpBody {
type Error;
}
impl HttpBody for () {
//~^ ERROR not all trait items implemented, missing: `Error`
// don't implement `Error` here for the ICE
}

pub struct Server<I, S>(I, S);

pub fn serve<I, S>(_: S) -> Server<I, S> {
todo!()
}

impl<S, B> Future for Server<(), S>
where
S: MakeServiceRef<(), (), ResBody = B>,
B: HttpBody,
B::Error: Debug,
{
type Output = ();

fn poll(self: Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
todo!()
}
}

pub trait MakeServiceRef<Target, ReqBody> {
type ResBody;
}

impl<T, S> MakeServiceRef<(), ()> for T
where
T: for<'a> Service<&'a (), Response = S>,
S: Service<()>,
{
type ResBody = ();
}

pub struct MakeServiceFn<F>(pub F);
pub struct ServiceFn<F, R>(pub PhantomData<(F, R)>);

pub trait Service<Request> {
type Response;
}

impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn<F>
where
F: Fn() -> Ret,
Ret: Future<Output = Result<Svc, ()>>,
{
type Response = Svc;
}

impl<F, ReqBody, Ret, ResBody, E> Service<ReqBody> for ServiceFn<F, ReqBody>
where
F: Fn() -> Ret,
Ret: Future<Output = Result<ResBody, E>>,
{
type Response = ResBody;
}
}

async fn smarvice() -> Result<(), ()> {
Ok(())
}

fn service_fn<F, R, S>(f: F) -> hyper::ServiceFn<F, R>
where
F: Fn() -> S,
{
hyper::ServiceFn(std::marker::PhantomData)
}

async fn iceice() {
let service = hyper::MakeServiceFn(|| async { Ok::<_, ()>(service_fn(|| smarvice())) });
hyper::serve::<(), _>(service).await;
}

fn main() {}
12 changes: 12 additions & 0 deletions src/test/ui/impl-trait/issue-103181-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0046]: not all trait items implemented, missing: `Error`
--> $DIR/issue-103181-1.rs:9:5
|
LL | type Error;
| ---------- `Error` from trait
LL | }
LL | impl HttpBody for () {
| ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation

error: aborting due to previous error

For more information about this error, try `rustc --explain E0046`.
29 changes: 29 additions & 0 deletions src/test/ui/impl-trait/issue-103181-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// edition:2021

trait SendFuture: Send {
type Output;
}

impl<Fut: Send> SendFuture for Fut {
type Output = ();
}

async fn broken_fut() {
ident_error;
//~^ ERROR cannot find value `ident_error` in this scope
}

// triggers normalization of `<Fut as SendFuture>::Output`,
// which requires `Fut: Send`.
fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {}

async fn iceice<A, B>()
// <- async fn is necessary
where
A: Send,
B: Send, // <- a second bound
{
normalize(broken_fut(), ());
}

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/impl-trait/issue-103181-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0425]: cannot find value `ident_error` in this scope
--> $DIR/issue-103181-2.rs:12:5
|
LL | ident_error;
| ^^^^^^^^^^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
1 change: 1 addition & 0 deletions src/test/ui/inference/char-as-str-single.fixed
Original file line number Diff line number Diff line change
@@ -8,4 +8,5 @@
fn main() {
let _: char = 'a'; //~ ERROR mismatched types
let _: char = '人'; //~ ERROR mismatched types
let _: char = '\''; //~ ERROR mismatched types
}
1 change: 1 addition & 0 deletions src/test/ui/inference/char-as-str-single.rs
Original file line number Diff line number Diff line change
@@ -8,4 +8,5 @@
fn main() {
let _: char = "a"; //~ ERROR mismatched types
let _: char = "人"; //~ ERROR mismatched types
let _: char = "'"; //~ ERROR mismatched types
}
15 changes: 14 additions & 1 deletion src/test/ui/inference/char-as-str-single.stderr
Original file line number Diff line number Diff line change
@@ -24,6 +24,19 @@ help: if you meant to write a `char` literal, use single quotes
LL | let _: char = '人';
| ~~~~

error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/char-as-str-single.rs:11:19
|
LL | let _: char = "'";
| ---- ^^^ expected `char`, found `&str`
| |
| expected due to this
|
help: if you meant to write a `char` literal, use single quotes
|
LL | let _: char = '\'';
| ~~~~

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
4 changes: 3 additions & 1 deletion src/test/ui/inference/str-as-char.fixed
Original file line number Diff line number Diff line change
@@ -4,5 +4,7 @@
// run-rustfix

fn main() {
let _: &str = "a"; //~ ERROR mismatched types
let _: &str = "a"; //~ ERROR mismatched types
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
}
4 changes: 3 additions & 1 deletion src/test/ui/inference/str-as-char.rs
Original file line number Diff line number Diff line change
@@ -4,5 +4,7 @@
// run-rustfix

fn main() {
let _: &str = 'a'; //~ ERROR mismatched types
let _: &str = 'a'; //~ ERROR mismatched types
let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
}
24 changes: 23 additions & 1 deletion src/test/ui/inference/str-as-char.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
error: character literal may only contain one codepoint
--> $DIR/str-as-char.rs:8:19
|
LL | let _: &str = '"""';
| ^^^^^
|
help: if you meant to write a `str` literal, use double quotes
|
LL | let _: &str = "\"\"\"";
| ~~~~~~~~

error: character literal may only contain one codepoint
--> $DIR/str-as-char.rs:9:19
|
LL | let _: &str = '\"\"\"';
| ^^^^^^^^
|
help: if you meant to write a `str` literal, use double quotes
|
LL | let _: &str = "\"\"\"";
| ~~~~~~~~

error[E0308]: mismatched types
--> $DIR/str-as-char.rs:7:19
|
@@ -11,6 +33,6 @@ help: if you meant to write a `str` literal, use double quotes
LL | let _: &str = "a";
| ~~~

error: aborting due to previous error
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
16 changes: 5 additions & 11 deletions src/tools/clippy/clippy_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -657,21 +657,18 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
let mut output = None;
let lang_items = cx.tcx.lang_items();

for pred in cx
for (pred, _) in cx
.tcx
.bound_explicit_item_bounds(ty.item_def_id)
.transpose_iter()
.map(|x| x.map_bound(|(p, _)| p))
.subst_iter_copied(cx.tcx, ty.substs)
{
match pred.0.kind().skip_binder() {
match pred.kind().skip_binder() {
PredicateKind::Trait(p)
if (lang_items.fn_trait() == Some(p.def_id())
|| lang_items.fn_mut_trait() == Some(p.def_id())
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
{
let i = pred
.map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1)))
.subst(cx.tcx, ty.substs);
let i = pred.kind().rebind(p.trait_ref.substs.type_at(1));

if inputs.map_or(false, |inputs| inputs != i) {
// Multiple different fn trait impls. Is this even allowed?
@@ -684,10 +681,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
// Multiple different fn trait impls. Is this even allowed?
return None;
}
output = Some(
pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap()))
.subst(cx.tcx, ty.substs),
);
output = pred.kind().rebind(p.term.ty()).transpose();
},
_ => (),
}